Spring getBean方法解析

  Spring的getBean流程是一个比较核心而又基础的方法,下面对里面的核心流程进行说明。

一、尝试从缓存中获取单例对象

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

这里是首先通过beanName来尝试获取单例对象的方法,这里面有几个比较重要的集合对象想要重点说明:

  • Map<String, Object> singletonObjects : 用来存储已经初始化过的单例对象
  • Map<String, Object> earlySingletonObjects : 这里保存的是一个只完成了构造器初始化的bean对象
  • Map<String, ObjectFactory<?>> singletonFactories : 这个是用来保存对象bean与构建工厂映射的,ObjectFactory里面有一个getObject方法,用于获取bean对象

说明了这几个对象之后我们就可以清楚的了解了上面一段代码的含义了:就是首先通过beanName到singletonObjects查找目标对象是否已经完成了初始化,如果存在直接拿走。但是如果不存在呢?那就去earlySingletonObjects中找,因为这里的对象已经完成了构造器注入,可以用来进行依赖注入需要,其实这个bean就是为了解决循环依赖问题的。如果这里也没有,那么就去singletonFactories找,通过调用getObject()方法获取到完成了构造器初始化的对象,并添加到earlySingletonObjects中。

 

那么说到这里就引发了两个问题:

  1. singletonFactories中的ObjectFactory对象是什么时候添加进去的?
  2. earlySingletonObjects中的对象什么时候会被添加到singletonObjects中?

二、如果单例缓存中不存在

  如果单例缓存中不存在,那么就需要创建一个单例对象。

                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

这里通过getSingleton方法来获取单例对象,我们看一下这个方法的声明

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {

可以看到第二个参数是一个ObjectFactory类型的对象,而ObjectFactory是一个函数式接口,所以 ()-> 定义的方法就是getObject()方法的实现。

在getSingleton方法中有一段这个代码:

try {
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }

这里调用了getObject()方法,其实调用的是函数式方法里面的creatBean()

        try {
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }

这里又调用了 doCreateBean 

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

真正的写入时机在这里 addSingletonFactory方法

    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized (this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                this.singletonFactories.put(beanName, singletonFactory);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }
        }
    }

在这里可以看到将ObjectFactory对象添加到singletonFactories中,earlySingletonObjects中移除是为了保证数据的正确性

到这里我们说明了第一个问题:singletonFactories中的工厂对象是从哪里来的

三、earlySingletonObjects中的对象什么时候被移除

刚才看到了 addSingletonFactory 方法,将一个只完成了构造器初始化的对象添加到对象工厂中,目的是为了支持后面循环依赖使用。但是在这个下面有一个比较重要的方法,这里不详细展开,但是一定要说明一下:

    /**
     * Populate the bean instance in the given BeanWrapper with the property values
     * from the bean definition.
     * @param beanName the name of the bean
     * @param mbd the bean definition for the bean
     * @param bw the BeanWrapper with bean instance
     */
    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

从方法的注释我们就可以知道,在这个方法中,会将对象的成员属性进行一一初始化。

这里我们掠过细节,其实只要知道,Spring是先完成对象的构造器初始化,然后就将对象工厂开放出去,然后再执行 populateBean 方法进行属性填充,这其中的时间可能会比较长。

下面咱们回到最开始调用createBean()的那里继续看

                try {
                    singletonObject = singletonFactory.getObject(); // 在这里调用createBean方法,就是上面的流程
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    // Has the singleton object implicitly appeared in the meantime ->
                    // if yes, proceed with it since the exception indicates that state.
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }

在这最后,看到如果是新创建的单例对象,那么会执行一个addSingleton的方法,看看去:

    /**
     * Add the given singleton object to the singleton cache of this factory.
     * <p>To be called for eager registration of singletons.
     * @param beanName the name of the bean
     * @param singletonObject the singleton object
     */
    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }

执行到这里我们知道目标单例对象已经完成初始化了,所有这里将对象添加到 singletonObjects 中,并将 singletonFactories 和  earlySingletonObjects 里面的中间对象移除掉,最后将其添加到registeredSingletons注册bean集合中

posted @ 2021-11-08 23:33  SyrupzZ  阅读(449)  评论(0)    收藏  举报