• Spring5源码分析(023)——IoC篇之bean加载:从缓存中获取单例 bean


    注:《Spring5源码分析》汇总可参考:Spring5源码分析(002)——博客汇总


      介绍完 FactoryBean 的小知识之后,我们就可以了解 bean 加载的过程了。前面提到过 bean 加载过程中首先会获取真正的 beanName (前面的文章已分析过),然后再通过 beanName 从单例缓存中尝试获取单例 bean ,本篇将就“从缓存中获取单例 bean”这一步进行讲解,其调用代码如下:
    /// org.springframework.beans.factory.support.AbstractBeanFactory
    
    // Eagerly check singleton cache for manually registered singletons.
    /*
     * 2、从缓存或者实例工厂中获取单例 bean 对象:检查缓存中或者实例工厂中是否有对应的 bean 实例
     * 为什么需要使用这段代码,来检查缓存?
     * 因为在创建单例 bean 的时候会存在依赖注入的情况,而在创建依赖的时候为了避免依赖循环,
     * Spring 创建 bean 的原则是不等 bean 创建完成就会将创建 bean 的 ObjectFactory 提前曝光,
     * 也就是将 ObjectFactory 加入到缓存中,一旦下个 bean 创建时需要依赖上个 bean 则直接使用 ObjectFactory
     */
    // 检查注册的单例缓存中是否有对应的单例
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        // 返回对应的实例,有时候存在诸如 FactoryBean 的情况下,可能返回 FactoryBean 本身,
        // 也有可能返回的是 FactoryBean 指定方法返回的实例
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

      本文目录结构如下:

     

    1、getSingleton

      前面提到过,单例在 Spring 的同一个容器内只会被创建一次,后续再获取 bean 时会直接从单例缓存中获取。当然,这里也只是尝试加载,首先尝试从单例缓存 singletonObjects 中加载,然后再次尝试从 earlySingletonObjects 中加载,之后再尝试从 singletonFactories 中获取,因为在创建单例 bean 的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring 创建 bean 的原则是不等 bean 创建完成就会将创建 bean 的 ObjectFactory 提早曝光加入到缓存中,一旦下一个 bean 创建时需要依赖上个 bean ,则直接使用 ObjectFactory。 AbstractBeanFactory#getSingleton(String beanName) 方法就是处理的这事,其内部代码如下:
    /// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
    
    @Override
    @Nullable
    public Object getSingleton(String beanName) {
        // 参数 allowEarlyReference 标识设置为 true 表示允许提前依赖引用
        return getSingleton(beanName, true);
    }
    
    /**
     * Return the (raw) singleton object registered under the given name.
     * <p>Checks already instantiated singletons and also allows for an early
     * reference to a currently created singleton (resolving a circular reference).
     * <p>返回在给定名称下注册的(原始)单例对象
     * <p>检查已实例化的单例,并允许提前引用当前正在创建中的单例(解析循环引用)。
     * @param beanName the name of the bean to look for
     * @param allowEarlyReference whether early references should be created or not
     * @return the registered singleton object, or {@code null} if none found
     */
    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 检查单例缓存中是否存在实例
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果为空,并且该 bean 正在创建中
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            // 加锁,锁住 singletonObjects 全局变量并进行处理
            synchronized (this.singletonObjects) {
                // 从 earlySingletonObjects 中获取
                // 如果该 bean 正在加载则不处理
                // 因为单例 singleton 是复用以前的创建的 bean ,因此需要检查是否已创建或者创建中
                singletonObject = this.earlySingletonObjects.get(beanName);
                // 只有 earlySingletonObjects 中不存在且允许提前创建,才会进行 singleton bean 的实例化
                if (singletonObject == null && allowEarlyReference) {
                    // 从 singletonFactories 中获取对应的 ObjectFactory
                    // 当某些方法需要提前初始化的时候会调用 addSingletonFactory 方法将对应的
                    // ObjectFactory 初始化策略存储在 singletonFactories 中
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        // 调用预先设定的 getObject 方法获得 bean
                        singletonObject = singletonFactory.getObject();
                        // 记录在缓存中, earlySingletonObjects 和 singletonFactories 互斥
                        // 添加 bean 到 earlySingletonObjects 中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        // 从 singletonFactories 移除对应的 ObjectFactory
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
      这个方法涉及到循环依赖的检测,其中又涉及到很多变量的记录存取,而这些变量则是解决循环依赖的关键所在。初看可能会觉得很绕口、很复杂,保持蛋定,莫慌,这段代码只是通过几个变量来判断完成,逻辑上还是比较简洁的,上面这个判断过程整理如下:
    • 第一步,首先尝试从单例缓存 singletonObjects 里面获取 bean 实例对象。
    • 第二步,如果获取不到,则再从 earlySingletonObjects 里面获取。
    • 第三步,如果还获取不到,且允许提前创建,则尝试从 singletonFactories 里面获取 beanName 对应的 ObjectFactory ,若不为空则调用 ObjectFactory#getObject() 来创建 bean ,然后放到 earlySingletonObjects 里面去,并且从 singletonFactories 里面删除掉 ,而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是在 allowEarlyReference 为 true 的情况下才会使用。
      这块的总体逻辑就是,检测与 beanName 有关的三个 Map ,如果为空,依次获取,否则返回,而这三个 Map 存储的 bean 都有各自的功能,这是解决循环依赖的关键所在,具体的说明如下:
    /// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
    
    /**
     * Cache of singleton objects: bean name to bean instance.
     * <p>单例 bean 实例对象的缓存映射: beanName --> bean 实例。
     * <p>保存实例化、初始化都完成的单例 bean 对象,称为【一级缓存】
     */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    /**
     * Cache of singleton factories: bean name to ObjectFactory.
     * <p>单例 Factory 缓存(创建 bean 的工厂)映射: beanName --> ObjectFactory。
     * <p>保存对象工厂 ObjectFactory ,用于创建二级缓存中的对象,称为【三级缓存】
     */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    /**
     * Cache of early singleton objects: bean name to bean instance.
     * <p>单例 bean 实例对象的缓存: beanName --> bean 实例。
     * <p>保存实例化完成、但是未初始化完成的提前曝光的对象,即早期的 bean ,称为【二级缓存】
     * <p>与 {@link #singletonObjects }的区别在于其存放的 bean 不一定是完整的,
     * 而从{@link #getSingleton(String) }中可以看到 bean 创建过程中就直接加入到 earlySingletonObjects
     * 中了,所以才可以通过 getBean 获取创建过程中的 bean ,这也是解决【循环依赖】 的关键所在
     */
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
     

    1.1、isSingletonCurrentlyInCreation(String beanName)

      这里也不要漏掉一个同样很重要的检测方法 isSingletonCurrentlyInCreation(String beanName) ,这个方法主要是判断该 beanName 对应的 bean 是否在创建中,代码如下:
    /// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
    
    /**
     * Names of beans that are currently in creation.
     * <p>当前正在创建中的 beans 的 beanName 集合
     */
    private final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    
    /**
     * Return whether the specified singleton bean is currently in creation
     * (within the entire factory).
     * <p>返回指定的单例bean当前是否正在创建(在整个 beanFactory 内)。
     * @param beanName the name of the bean
     */
    public boolean isSingletonCurrentlyInCreation(String beanName) {
        return this.singletonsCurrentlyInCreation.contains(beanName);
    }

      结合前面提到的,首先需要获取是否有已经实例化完整的 bean ,如果没有而且允许提前创建,这个时候才会去查找创建过程中的 bean 。因此可以猜到,bean 创建过程中都会加入到 singletonsCurrentlyInCreation 集合中,这样就知道哪些在创建中可以提前返回引用了,否则就很难判断实例化过程中的循环依赖了。至于创建过程中是在哪里、什么时候加的,后面会分析到。(注:后面 DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory) 中的创建前的前置处理中默认会用到)

     

    2、getObjectForBeanInstance

      在 getBean 方法中, getObjectForBeanInstance 是个高频使用的方法,无论是从缓存中获的 bean 还是根据不同的 scope 策略加载 bean 。总之,我们得到 bean 的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是用于检测当前 bean 是否是 FactroyBean 类型的 bean,如果是,那么需要调用该 bean 对应的 FactoryBean 实例中的 getObject() 作为返回值。
      再说详细一点:因为无论是从缓存中获取到的 bean 还是通过不同的 scope 策略加载的 bean 都只是最原始的 bean ,也即是说,缓存中记录的只是最原始的 bean 状态,并不一定是我们最终想要的 bean 。举个例子,当我们需要对 FactoryBean 即工厂 bean 进行处理,那么这里得到的其实是工厂 bean 的初始状态,但是我们真正需要的是工厂 bean 中定义的 factory-method 方法中返回的 bean ;另外也有可能我们需要返回的就是 FactoryBean 本身,而 #getObjectForBeanInstance 方法就是来完成这些处理的,代码如下:
    /**
     * Get the object for the given bean instance, either the bean
     * instance itself or its created object in case of a FactoryBean.
     * <p>获取给定Bean实例的对象,如果是 FactoryBean ,则获取Bean实例本身或其创建的对象。
     * @param beanInstance the shared bean instance
     * @param name name that may include factory dereference prefix
     * @param beanName the canonical bean name
     * @param mbd the merged bean definition
     * @return the object to expose for the bean
     */
    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
        // Don't let calling code try to dereference the factory if the bean isn't a factory.
        // 1、如果指定的 name 是工厂类相关,即 & 前缀
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            // 如果是 NullBean 类型则直接返回
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            // beanInstance 不是 FactoryBean 类型则验证不通过,抛出异常
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
            // 设置 isFactoryBean 标识为 true
            if (mbd != null) {
                mbd.isFactoryBean = true;
            }
            // 返回工厂 bean 本身
            return beanInstance;
        }
    
        // Now we have the bean instance, which may be a normal bean or a FactoryBean.
        // If it's a FactoryBean, we use it to create a bean instance, unless the
        // caller actually wants a reference to the factory.
        // 到这里我们已经有了一个 bean 实例,该实例可能是普通的 bean 或者是 FactoryBean,
        // 如果是 FactoryBean ,我们需要使用它来创建 bean 实例 ,除非是需要 FactoryBean 本身
        // 2、非 FactoryBean 的普通 bean ,直接返回
        if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }
    
        Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        else {
            // 3、如果 RootBeanDefinition 为 null,则尝试从 factoryBeanObjectCache 缓存中加载 bean
            object = getCachedObjectForFactoryBean(beanName);
        }
        // 若 object 依然为空,而到这里可以确认 beanInstance 一定是 FactoryBean 类型,则使用 FactoryBean 来创建 bean
        if (object == null) {
            // Return bean instance from factory.
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // 检测 beanDefinitionMap 中也就是在所有已经加载的类中检测是否定义 beanName
            // Caches object obtained from FactoryBean if it is a singleton.
            if (mbd == null && containsBeanDefinition(beanName)) {
                // 将存储 XML 配置的 GenericBeanDefinition 转换成 RootBeanDefinition ,
                // 如果指定的 beanName 是子bean的话同时会合并父类的相关属性
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            // 是否是用户定义的而不是应用程序本身定义的
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            // 使用 FactoryBean 获得 Bean 实例对象
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }

      这个方法主要做了如下处理:

    • 1、校验 beanInstance 的正确性:如果指定的 name 是工厂类相关的( & 前缀)且 beanInstance 是 NullBean 类型则直接返回;如果 beanInstance 不是 FactoryBean 类型则抛出 BeanIsNotAFactoryException 异常;是 FactoryBean 则直接返回了。这个是需要返回 FactoryBean 本身的场景,后面则是需要返回 bean 实例。
    • 2、如果 beanInstance 不是 FactoryBean 类型,则直接返回该实例。
    • 3、如果 BeanDefinition 为空(前面调用传的就是空),则从 factoryBeanObjectCache 缓存中获取 bean 实例对象,如果还是为空,我们知道此时 beanInstance 肯定已经是 FactoryBean 类型,需要处理的就是通过 FactoryBean 来获得对应的 bean 实例,这里是通过委托 FactoryBeanRegistrySupport#getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) 方法来处理,可以猜想到的是,里面会调用 #getObject() 方法,获得最终自定义的 bean 实例。
     
      总之,这里区分了2种场景来处理:
    • 第1种是非 FactoryBean 类型,直接返回 bean 实例对象 beanInstance
    • 第2种就是 FactoryBean 类型,当然,如果确实是需要返回工厂类本身,这里直接就返回了 beanInstance ;如果不是,则是通过 FactoryBean 来获取实际的 bean 实例对象,也就是 #getObjectFromFactoryBean(...) 方法所作的事情。
      接下来我们把目光转移到核心方法 #getObjectFromFactoryBean 上。
     

    2.1、getObjectFromFactoryBean

      代码如下:
    /**
     * Obtain an object to expose from the given FactoryBean.
     * <p>从给定的 FactoryBean 中获取对象实例
     * @param factory the FactoryBean instance
     * @param beanName the name of the bean
     * @param shouldPostProcess whether the bean is subject to post-processing
     * @return the object obtained from the FactoryBean
     * @throws BeanCreationException if FactoryBean object creation failed
     * @see org.springframework.beans.factory.FactoryBean#getObject()
     */
    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        // 1、如果是单例模式且缓存中存在
        if (factory.isSingleton() && containsSingleton(beanName)) {
            // 1.1、对单例缓存加锁
            synchronized (getSingletonMutex()) {
                // 1.2、从缓存中获取指定的 bean 实例
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    // 1.3、缓存中没有,则通过 FactoryBean 获取 bean 实例
                    object = doGetObjectFromFactoryBean(factory, beanName);
                    // 从缓存中获取,如果缓存中已经存在,则使用缓存中的实例
                    // Only post-process and store if not put there already during getObject() call above
                    // (e.g. because of circular reference processing triggered by custom getBean calls)
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }
                    else {
                        // 1.4、需要后续处理
                        if (shouldPostProcess) {
                            // 如果 bean 实例还在创建中,则直接返回该对象实例
                            if (isSingletonCurrentlyInCreation(beanName)) {
                                // Temporarily return non-post-processed object, not storing it yet..
                                return object;
                            }
                            // 单例 bean 的创建前处理
                            beforeSingletonCreation(beanName);
                            try {
                                // 对从 FactoryBean 获取的实例进行后处理,主要是后处理器 BeanPostProcessor 处理
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                            finally {
                                // 单例 bean 创建完后置处理
                                afterSingletonCreation(beanName);
                            }
                        }
                        // 1.5、添加到 factoryBeanObjectCache 缓存中
                        if (containsSingleton(beanName)) {
                            this.factoryBeanObjectCache.put(beanName, object);
                        }
                    }
                }
                return object;
            }
        }
        else {
            // 2、不是单例模式,则从 FactoryBean 中获取
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            // 2.1、需要后续处理
            if (shouldPostProcess) {
                try {
                    // 对从 FactoryBean 获取的实例进行后处理,主要是后处理器 BeanPostProcessor 处理
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }
      #getObjectFromFactoryBean 方法的主要处理流程如下:
    • 1、如果 FactoryBean 是单例模式且【一级缓存singletonObjects 中存在相关的 beanName ,则进行后续处理,否则按照非单例模式处理(第2步)
      • 1.1、首先,就是获取单例缓存 singletonObjects 的锁。可以发现,前面很多解析中也提到了 singletonObjects 的对象锁,这里是为了保证单例实例在单例模式中的唯一性,代码如下:
    /// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
    
    /**
     * Cache of singleton objects: bean name to bean instance.
     * <p>单例 bean 实例对象的缓存映射: beanName --> bean 实例。
     * <p>保存实例化、初始化都完成的单例 bean 对象,称为【一级缓存】
     */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    @Override
    public final Object getSingletonMutex() {
        return this.singletonObjects;
    }
      •  1.2、其次,从缓存 factoryBeanObjectCache 中获取 bean 实例。如果存在,说明之前已经处理过,直接返回。
      • 1.3、如果不存在,则调用 #doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) 方法,从 FactoryBean 获取实例对象,内部其实就是调用了我们一直提到的 FactoryBean#getObject() 方法,代码如下,中间可以看到,确实是调用了 #getObject() 来获取实例对象:
    /// org.springframework.beans.factory.support.FactoryBeanRegistrySupport
    
    /**
     * Obtain an object to expose from the given FactoryBean.
     * <p>从给定的 FactoryBean 中获取对象实例
     * @param factory the FactoryBean instance
     * @param beanName the name of the bean
     * @return the object obtained from the FactoryBean
     * @throws BeanCreationException if FactoryBean object creation failed
     * @see org.springframework.beans.factory.FactoryBean#getObject()
     */
    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((PrivilegedExceptionAction<Object>) factory::getObject, acc);
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                // 直接调用 getObject 方法获取 bean 实例
                object = factory.getObject();
            }
        }
        catch (FactoryBeanNotInitializedException ex) {
            throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }
    
        // Do not accept a null value for a FactoryBean that's not fully
        // initialized yet: Many FactoryBeans just return null then.
        if (object == null) {
            // 如果当前 bean 正在创建中,则抛出异常
            if (isSingletonCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(
                        beanName, "FactoryBean which is currently in creation returned null from getObject");
            }
            // getObject 返回 null 则是统一使用 NullBean
            object = new NullBean();
        }
        return object;
    }
      • 1.4、如果需要对新创建的 bean 实例进行后续处理,则
        • 如果该 bean 实例对象还在创建中,即 DefaultSingletonBeanRegistry#isSingletonCurrentlyInCreation(String beanName) 方法返回 true ,则直接返回该对象,无需进一步处理。
        • 调用 #beforeSingletonCreation(String beanName) 方法,进行创建之前的处理,默认实现是将该 bean 注册为正在创建中
        • 调用 #postProcessObjectFromFactoryBean(Object object, String beanName) 对从 FactoryBean 获取的实例进行后处理,主要扩展是后处理器 BeanPostProcessor 处理
        • 调用 #afterSingletonCreation(String beanName) 方法,进行 bean 对象实例创建完后处理,默认实现是将该 bean 标记为不在创建中,也即是从正在创建中移除
      • 1.5、将获得的 bean 对象添加到 1.2 中提到 factoryBeanObjectCache 中,以便下次获取该单例。
    • 2、此时已经知道是非单例模式,则直接调用 #doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) 方法,从 FactoryBean 获取实例对象,当然,这里如果需要后续处理的话,只需要调用 #postProcessObjectFromFactoryBean(Object object, String beanName) 对从 FactoryBean 获取的实例进行后处理,因为非单例模式并不需要标记状态,而是直接使用。
      至此我们已经基本了解了【bean的实例化】涉及到的核心方法 #getObjectFromFactoryBean 的处理流程。当然,这当中还涉及到了一些很眼熟而且需要我们关注的几个方法:
    • #isSingletonCurrentlyInCreation(String beanName)
    • #beforeSingletonCreation(String beanName)
    • #postProcessObjectFromFactoryBean(Object object, String beanName)
    • #afterSingletonCreation(String beanName)
     

    2.2、isSingletonCurrentlyInCreation

      #isSingletonCurrentlyInCreation 方法主要用于检测 bean 当前是否在创建中,它记录着 bean 的加载状态,配合 #beforeSingletonCreation(String beanName)#afterSingletonCreation(String beanName) 这两方法,对循环依赖的判断有很大的作用。
    • #beforeSingletonCreation(String beanName):创建 bean 前调用,将该 beanName 标记为正在创建中;
    • #afterSingletonCreation(String beanName):创建 bean 后调用,将该 beanName 移除正在创建中的标记。
    这一前一后的标记和移除标记,有利于在循环依赖中进行检测,使得可以提前引用正在创建中的 bean 。代码如下:
    /// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
    
    /**
     * Names of beans that are currently in creation.
     * <p>当前正在创建中的 beans 的 beanName 集合
     */
    private final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    
    /**
     * Return whether the specified singleton bean is currently in creation
     * (within the entire factory).
     * <p>返回指定的单例bean当前是否正在创建(在整个 beanFactory 内)。
     * @param beanName the name of the bean
     */
    public boolean isSingletonCurrentlyInCreation(String beanName) {
        return this.singletonsCurrentlyInCreation.contains(beanName);
    }
     

    2.3、beforeSingletonCreation

      在单例创建前添加标志到 singletonsCurrentlyInCreation 中,表示正处于创建中状态,代码如下:
    /// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
    
    /**
     * Callback before singleton creation.
     * <p>The default implementation register the singleton as currently in creation.
     * <p>单例创建前回调,默认实现是将单例注册为正在创建中
     * @param beanName the name of the singleton about to be created
     * @see #isSingletonCurrentlyInCreation
     */
    protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }

    2.4、afterSingletonCreation

      在单例创建后从 singletonsCurrentlyInCreation 中移除标志,表示不再处于创建中状态,代码如下:

    /// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
    
    /**
     * Callback after singleton creation.
     * <p>The default implementation marks the singleton as not in creation anymore.
     * <p>单例创建后回调,默认实现是标记单例不在创建中,即从正在创建中移除
     * @param beanName the name of the singleton that has been created
     * @see #isSingletonCurrentlyInCreation
     */
    protected void afterSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
            throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
        }
    }

    2.5、postProcessObjectFromFactoryBean

      FactoryBeanRegistrySupport#postProcessObjectFromFactoryBean(Object object, String beanName) 方法主要是扩展进行后置处理,org.springframework.beans.factory.support.FactoryBeanRegistrySupport 中默认是空实现不进行处理,直接返回实例对象。代码如下:

    /**
     * Post-process the given object that has been obtained from the FactoryBean.
     * The resulting object will get exposed for bean references.
     * <p>The default implementation simply returns the given object as-is.
     * Subclasses may override this, for example, to apply post-processors.
     * @param object the object obtained from the FactoryBean.
     * @param beanName the name of the bean
     * @return the object to expose
     * @throws org.springframework.beans.BeansException if any post-processing failed
     */
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
        return object;
    }

      注释里面提到,子类可以重写此方法,用于扩展进行进行后置处理。我们看下 Spring 中已经提供的实现: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

     

    2.6、AbstractAutowireCapableBeanFactory

      AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean 方法代码如下:
    /// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
    
    /**
     * Applies the {@code postProcessAfterInitialization} callback of all
     * registered BeanPostProcessors, giving them a chance to post-process the
     * object obtained from FactoryBeans (for example, to auto-proxy them).
     * <p>应用所有注册的 BeanPostProcessors 的 postProcessAfterInitialization 回调,
     * 使它们有机会对从 FactoryBeans 获取的对象进行后处理(例如,自动代理它们)。
     * @see #applyBeanPostProcessorsAfterInitialization
     */
    @Override
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
        return applyBeanPostProcessorsAfterInitialization(object, beanName);
    }
    
    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {
    
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

      可以看到, AbstractAutowireCapableBeanFactory 中的实现主要用于后处理器 BeanPostProcessor 对创建完的 bean 实例进行处理。关于后处理器的使用,本文暂且不表,后续文章将会进行详细的分析和介绍。这里,我们只需要了解在 Spring 获取 bean 的规则中有这样一条:尽可能保证所有 bean 初始化后都会调用注册的 BeanPostProcessor#postProcessAfterInitialization 方法进行处理,在实际开发过程中大可以针对此特性设计自己的业务逻辑。

     

    3、参考

  • 相关阅读:
    (转)Linux下/etc/rc.local与/etc/init.d的区别与联系
    (转)谈免驱
    (转)获取android源码时repo的错误
    (转)platform_driver_register,什么时候调用PROBE函数 注册后如何找到驱动匹配的设备
    (转)typedef 函数指针的用法
    (转)分析kernel的initcall函数
    (转)Tiny210v2( S5PV210 ) 平台下 FIMD 对应 的 framebuffer 驱动中,关于 video buffer 的理解
    tiny210V2开发板hdmi输出到10.1寸LCD,无图像
    (转)学习linux的几本书
    (转)RGB接口和i80接口的区别
  • 原文地址:https://www.cnblogs.com/wpbxin/p/14928877.html
Copyright © 2020-2023  润新知