zoukankan      html  css  js  c++  java
  • Spring(十四):使用FactoryBean配置Bean

    FactoryBean简介:

    1)Spring中Bean包含两种一种是普通Bean,另外一种是FactoryBean。它们都受IOC容器管理,但是也有不同之处。

    2)普通Bean与FactoryBean的区别:

    a)普通的Bean只需要定义好,然后配置文件中定义并配置其依赖关系,就可以通过IOC容器的getBean获取到;

    b)FactoryBean是实现了FactoryBean<T>接口的Bean,通过FactoryBean类的getBean方法直接获取到的并不是该FactoryBean实例,而是FactoryBean中方法getObject返回的对象。

    c)FactoryBean的实例可以通过其他方法获取到,在通过getBean方法获取实例时在参数name前面加上“&”符号即可。

    FactoryBean的接口定义如下:

    public interface FactoryBean<T> {  
        //获取FactoryBean初始化的Bean实例  
        T getObject() throws Exception;  
        //获取Bean实例的类型  
        Class<?> getObjectType();  
        //判断是否是单例模式  
        default boolean isSingleton() {
            return true;
        }    
    }

    示例:

    定义Category.java

    package com.dx.spring.beans.factorybean;
    
    public class Category {
        private Integer id;
        private String name;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Category(Integer id, String name) {
            super();
            this.id = id;
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Category [id=" + id + ", name=" + name + "]";
        }
    
    }

    定义CategoryFactoryBean.java

    package com.dx.spring.beans.factorybean;
    
    import org.springframework.beans.factory.FactoryBean;
    
    public class CategoryFactoryBean implements FactoryBean<Category> {
    
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public Category getObject() throws Exception {
            System.out.println(this.name);
            return new Category(1, "java spring");
        }
    
        @Override
        public Class<?> getObjectType() {
            return Category.class;
        }
    
        @Override
        public boolean isSingleton() {
            return FactoryBean.super.isSingleton();
        }
    
    }

    新建spring bean配置文件bean-factorybean.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="category" class="com.dx.spring.beans.factorybean.CategoryFactoryBean">
            <property name="name" value="hello factorybean"></property>
        </bean>
    </beans>

    添加测试类Client.java并测试:

    package com.dx.spring.beans.factorybean;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Client {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factorybean.xml");
            Category category = (Category) ctx.getBean("category");    
            System.out.println(category);
    
            CategoryFactoryBean categoryFactoryBean = (CategoryFactoryBean) ctx.getBean("&category");    
            System.out.println(categoryFactoryBean);
        }
    }

    打印信息为:

    hello factorybean
    Category [id=1, name=java spring]
    com.dx.spring.beans.factorybean.CategoryFactoryBean@1e397ed7

    实现原理:

    声明:以下参考《Spring源码学习--FactoryBean实现原理

    当程序执行Category category = (Category) ctx.getBean("category");时,在AbstractBeanFactory中会进行一系列的操作:

    getBean获取bean

        @Override
        public Object getBean(String name) throws BeansException {
            return doGetBean(name, null, null, false);
        }

    doGetBean中获取bean实例

    protected <T> T doGetBean(  
                final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)  
                throws BeansException {  
            .........//省略部分代码  
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  
            .........//省略部分代码  
            return (T) bean;  
        }  

    getObjectForBeanInstance中会选择bean实例是普通的Bean还是FactoryBean,同时通过判断name中是否有&来选择判断是或者FactoryBean还是其getObject方法中获取的bean

    protected Object getObjectForBeanInstance(  
                Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {  
            .........//省略部分代码  
            //判断bean类型是否是FactoryBean,或者name是否是以&开头,如果是则直接返回  
            if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {  
                return beanInstance;  
            }  
            //如果是则从getObjectFromFactoryBean中获取  
            if (object == null) {  
                // Return bean instance from factory.  
                FactoryBean<?> factory = (FactoryBean<?>) beanInstance;  
                if (mbd == null && containsBeanDefinition(beanName)) {  
                    mbd = getMergedLocalBeanDefinition(beanName);  
                }  
                boolean synthetic = (mbd != null && mbd.isSynthetic());  
                object = getObjectFromFactoryBean(factory, beanName, !synthetic);  
            }  
            return object;  
        }  

    getObjectFromFactoryBean接下来会执行FactoryBean的getObject方法获取bean了。

    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {  
            .........//省略部分代码                 
            Object object = doGetObjectFromFactoryBean(factory, beanName);  
            .........//省略部分代码  
            return object;  
        }  
          
    private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)  
                throws BeanCreationException {  
            Object object;  
            .........//省略部分代码  
            //调用Factory的getObject方法  
            object = factory.getObject();  
            .........//省略部分代码  
            return object;  
        }  
  • 相关阅读:
    Redis实战之Redis + Jedis[转]
    FastDFS、nginx配置手记
    服务器后端开发系列——《实战FastDFS分布式文件系统》[转]
    FastDFS分布文件系统[转]
    在XMPP的JAVA开源实现Openfire中,增加LBS 附近的人功能
    FASTDFS 5X安装
    助力互联网创业融资
    lucene索引并搜索mysql数据库[转]
    ZooKeeper监控
    光驱在资源管理器显示黄色感叹号的解决方法BIOS内有 系统下没有
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/9090940.html
Copyright © 2011-2022 走看看