FactoryBean实现

1、概述
spring中有两种类型的Bean:一种是普通的JavaBean;另一种就是工厂Bean(FactoryBean),这两种Bean都受Spring的IoC容器管理,但它们之间却有一些区别。

2、详述
普通的JavaBean不再多说,我们将其定义好,然后在配置文件中定义并配置其依赖关系,就可以通过IoC容器的getBean获取到。

那么FactoryBean呢?

FactoryBean跟普通Bean不同,它是实现了FactoryBean接口的Bean,通过BeanFactory类的getBean方法直接获取到的并不是该FactoryBean的实例,而是该FactoryBean中方法getObject返回的对象。但我们可以通过其它途径获取到该FactoryBean的实例,方法就是在通过getBean方法获取实例时在参数name前面加上“&”符号即可。

FactoryBean接口提供的方法如下:

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

3、示例
创建MyFactoryBean:

public class MyFactoryBean implements FactoryBean<Date>,BeanNameAware {  
    private String name;  
    @Override  
    public Date getObject() throws Exception {  
        return new Date();  
    }  
    @Override  
    public Class<?> getObjectType() {  
        return Date.class;  
    }  
    @Override  
    public boolean isSingleton() {  
        return false;  
    }  
    public void sayName() {  
        System.out.println("My name is " + this.name);  
    }  
    @Override  
    public void setBeanName(String name) {  
        this.name = name;  
    }  
}  

在Spring的配置文件ApplicationContext.xml中注入MyFactoryBean

测试代码

public class MainFactoryBean {

    @SuppressWarnings("resource")
    public static void main(String [] args){  
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Date now = (Date) appCtx.getBean("myFactoryBean");  
        System.out.println(now);  
        MyFactoryBean factoryBean = (MyFactoryBean) appCtx.getBean("&myFactoryBean");  
        factoryBean.sayName();  
    }  
}

运行结果:通过myFactoryBean名称获取到的Bean是Date对象实例,通过&myFactoryBean获取到的是MyFactoryBean对象实例。

4、实现原理
我们来看一下执行Date now = (Date) appCtx.getBean(“myFactoryBean”); 时会做的处理操作。
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;
    }

总结:Spring对FactoryBean的实现机制是当你获取一个Bean时,如果获取的Bean的类型是FactoryBean,并且其name中并没有&则调用bean的getObject方法获取FactoryBean实现类中提供bean,否则就是直接返回普通的bean类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值