Spring系列之FactoryBean(二)

简介: 我们在上一篇文章中说了一下FactoryBean类型的Bean的getObjectType方法被使用到的一个地方,我们在这一篇文章中会说一下FactoryBean是怎么让Spring容器管理调用它的getObject所生成的Bean的。

我们在上一篇文章中说了一下FactoryBean类型的Bean的getObjectType方法被使用到的一个地方,我们在这一篇文章中会说一下FactoryBean是怎么让Spring容器管理调用它的getObject所生成的Bean的。在这篇文章中我们从getBean方法开始说起(我们这里还是要说一下我们现在的beanName的值为:factoryBeanLearn,Class类型为:FactoryBeanService.class ):
getBean(beanName, requiredType, args)方法,这个方法又调用了doGetBean方法,doGetBean可以说是Spring容器中一个很核心的一个类,里面的功能很多很复杂,我们在这篇文章中只关注和FactoryBean相关的内容。思路是:先分析大内容里面的具体的点,再由点及面的分析。

public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
    return doGetBean(name, requiredType, args, false);
}
protected <T> T doGetBean(
    final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
        throws BeansException {
    //转换传入的BeanName的值,如&name变为name 以及别名(alias)的转换
    final String beanName = transformedBeanName(name);
    Object bean;
    //调用getSingleton方法 从Spring容器中获取单例Bean 具体的获取过程见下面分析
    //我们在上一篇文章中分析过 这里的beanName为factoryBeanLearn 
    //beanName为factoryBeanLearn的Bean 已经在Spring容器中创建过了(创建过程见AbstractApplicationContext的refresh方法)
    //所以这里会获取到一个FactoryBeanLearn实例
    //这里根据beanName获取bean实例的方法 beanName都是经过处理之后的beanName
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        //这个方法是从实例自身获取对象 像这个实例是一个FactoryBean类型的实例
        //我们在下面分析这个方法
        //这里要注意的是:我们在这个方法中传入了一个name 又传入了一个beanName
        //这里为什么要传入两个beanName?可以想一下
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

getSingleton从Spring容器中获取单例Bean

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //先从singletonObjects中获取单例Bean singletonObjects是一个ConcurrentHashMap
        //key是beanName value是单例Bean
        Object singletonObject = this.singletonObjects.get(beanName);
        //如果没有获取到,则判断是不是当前在创建中的单例Bean
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //这里加锁
            synchronized (this.singletonObjects) {
                //提前暴露创建的Bean中是否存在beanName的单例Bean
                singletonObject = this.earlySingletonObjects.get(beanName);
                //如果没有获取到 并且允许提前引用响应的Bean
                if (singletonObject == null && allowEarlyReference) {
                    //singletonFactories是一个HashMap key是beanName,value是ObjectFactory 又一个Factory
                    //在Spring中很多地方用到了ObjectFactory  包括我们在之前的文章中分析的 Autowired Request
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        //从ObjectFactory中获取Bean实例
                        singletonObject = singletonFactory.getObject();
                        //放入earlySingletonObjects这个Map中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

getObjectForBeanInstance的分析

    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

        //这里判断 name是不是以&开头,不是经过处理的beanName  并且这个bean实例 不是FactoryBean类型的
        //如果是&开头 并且不是FactoryBean类型 则抛出异常
        if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }
        
        //不是FactoryBean类型 或者name以&开头 直接返回bean实例
        //想一下我们关于FactoryBean的知识:如果要根据beanName获取真正的FactoryBean实例的时候
        //需要在beanName前面加上&  这里就可以看到为什么要这样做了。
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }

        Object object = null;
        if (mbd == null) {
            //factoryBeanObjectCache 看看是不是在缓存中存在
            //factoryBeanObjectCache
            object = getCachedObjectForFactoryBean(beanName);
        }
        //如果没有 
        if (object == null) {
            //如果能走到这里来 这个bean实例是FactoryBean类型的
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            if (mbd == null && containsBeanDefinition(beanName)) {
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            //从这个方法的名字我们可以看到这个方法的意思是:从FactoryBean中
            //获取对象
            //getObjectFromFactoryBean的分析在下面 
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }

getObjectFromFactoryBean的分析

    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        //FactoryBean类型的实例 调用isSingleton方法返回的是true 
        //所传入的bean实例也要求是单例类型的
        //对应我们这里就是FactoryBeanLearn中的方法返回true 
        if (factory.isSingleton() && containsSingleton(beanName)) {
            //加锁
            synchronized (getSingletonMutex()) {
                //再从缓存中获取一次
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    //调用doGetObjectFromFactoryBean方法从FactoryBean中获取bean对象
                    //这里是调用的FactoryBean的getObject方法来获取的
                    object = doGetObjectFromFactoryBean(factory, beanName);
                    //再从缓存中获取一次
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    //如果上一步的缓存中获取到了 则用缓存中的替代我们
                    //我们从FactoryBean中获取的bean
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }
                    else {
                        if (object != null && shouldPostProcess) {
                            try {
                                //调用BeanPostProcessor中的postProcessAfterInitialization方法进行处理
                                //这里只会调用BeanPostProcessor的postProcessAfterInitialization方法了
                                //
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            //抛出异常
                        }
                        //放入到factoryBeanObjectCache中缓存起来  key为beanName
                        this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
                    }
                }
                return (object != NULL_OBJECT ? object : null);
            }
        }
        else {
            //非单例
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (object != null && shouldPostProcess) {
                try {
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }

doGetObjectFromFactoryBean的分析

    private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
            throws BeanCreationException {

        Object object;
        try {
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = getAccessControlContext();
                try {
                    object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                                //调用FactoryBean中的getObject()方法获取bean
                                return factory.getObject();
                            }
                        }, acc);
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                //看这里 调用FactoryBean中的getObject()方法获取bean
                object = factory.getObject();
            }
        }
        if (object == null && isSingletonCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(
                    beanName, "FactoryBean which is currently in creation returned null from getObject");
        }
        return object;
    }

整个流程图大致如下:
FactoryBean

流程简化起来就是:

循环Spring容器中所有的beanNames,再根据beanName获取对应的Bean实例,判断获取的Bean实例是不是FactoryBean类型的Bean,如果是,则调用Bean的getObjectType方法获取Class,将获取到的Class和传入的Class进行匹配,如果匹配到,则将此beanName和传入的Class建立一个映射关系。再根据beanName获取到Spring容器中对应的Bean,调用Bean的getObject方法来获取对应的实例。
相关文章
|
7月前
|
Java 关系型数据库 MySQL
Spring5深入浅出篇:Spring中的FactoryBean对象
Spring5深入浅出篇:Spring中的FactoryBean对象
|
Java Spring 容器
Spring中BeanFactory和FactoryBean的区别?
一位工作了4年的小伙伴,去京东面试被问到这样一个问题,Spring中的BeanFactory和FactoryBean有什么区别?因为没有看过源码,当时就感觉这是一个文字游戏,感觉没什么区别? 那今天,我就给大家来聊清楚。另外,往期面试题解析中配套的文档我已经准备好,想获得的可以在我的煮叶简介中找到。好了,我们先来看BeanFactory。
66 0
|
7月前
|
XML Java 数据格式
spring中怎么通过静态工厂和动态工厂获取对象以及怎么通过 FactoryBean 获取对象
spring中怎么通过静态工厂和动态工厂获取对象以及怎么通过 FactoryBean 获取对象
85 0
|
2月前
|
缓存 JavaScript Java
Spring之FactoryBean的处理底层源码分析
本文介绍了Spring框架中FactoryBean的重要作用及其使用方法。通过一个简单的示例展示了如何通过FactoryBean返回一个User对象,并解释了在调用`getBean()`方法时,传入名称前添加`&`符号会改变返回对象类型的原因。进一步深入源码分析,详细说明了`getBean()`方法内部对FactoryBean的处理逻辑,解释了为何添加`&`符号会导致不同的行为。最后,通过具体代码片段展示了这一过程的关键步骤。
Spring之FactoryBean的处理底层源码分析
|
2月前
|
XML 缓存 Java
Spring FactoryBean 的常见使用场景总结
FactoryBean 是 Spring 框架中的一个重要接口,用于自定义 Bean 的创建逻辑。常见使用场景包括: 1. **复杂 Bean 的创建**:如数据源配置。 2. **延迟实例化**:按需创建资源密集型对象。 3. **动态代理**:为 Bean 创建 AOP 代理。 4. **自定义配置**:根据特定配置创建 Bean。 5. **第三方库集成**:利用 FactoryBean 封装外部库的创建过程。
|
7月前
|
Java 数据库连接 API
【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】
【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】
103 0
|
6月前
|
Java Spring
聊聊Spring中两种创建Bean的方式:BeanDefinition.setInstanceSupplier() 和 FactoryBean
聊聊Spring中两种创建Bean的方式:BeanDefinition.setInstanceSupplier() 和 FactoryBean
|
7月前
|
XML Java 数据格式
Spring5源码(8)-BeanFactory和FactoryBean的区别
Spring5源码(8)-BeanFactory和FactoryBean的区别
66 0
|
XML Java 数据格式
Spring中BeanFactory和FactoryBean详解
Spring中BeanFactory和FactoryBean详解
316 1
|
7月前
|
XML Java 数据格式
③【Spring】整合第三框架的常用机制:FactoryBean
③【Spring】整合第三框架的常用机制:FactoryBean
90 0