zoukankan      html  css  js  c++  java
  • 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、参考

  • 相关阅读:
    out/host/linuxx86/obj/EXECUTABLES/aapt_intermediates/aapt 64 32 操作系统
    linux 查看路由器 电脑主机 端口号 占用
    linux proc进程 pid stat statm status id 目录 解析 内存使用
    linux vim 设置大全详解
    ubuntu subclipse svn no libsvnjavahl1 in java.library.path no svnjavahl1 in java.library.path no s
    win7 安装 ubuntu 双系统 详解 easybcd 工具 不能进入 ubuntu 界面
    Atitit.json xml 序列化循环引用解决方案json
    Atitit.编程语言and 自然语言的比较and 编程语言未来的发展
    Atitit.跨语言  文件夹与文件的io操作集合  草案
    Atitit.atijson 类库的新特性设计与实现 v3 q31
  • 原文地址:https://www.cnblogs.com/wpbxin/p/14928877.html
Copyright © 2011-2022 走看看