天天看點

Spring Bean生命周期-getBean方法(十)

前面提的基本上都是ApplicationContext的refresh方法,在分析的過程中bean容器的基本啟動過程心中有了大體的了解,分析過程中,我們發現bean的執行個體化及加工相關的處理都在getBean方法中,一起看下getBean方法。

@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}
           

doGetBean的方法比較長,拆開分析

分析

  1. 從緩存中,或者擷取手動注冊的bean,也就是單例的bean已經被建立過了,那麼直接擷取。
final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
           

getObjectForBeanInstance主要做了如下事情:

  • 如果sharedInstance不是FactoryBean的執行個體,也不是Factory的引用,直接傳回sharedInstance
  • 從緩存中擷取FactoryBean建立的Bean執行個體
  • 如果換成中沒有,那麼使用FactoryBean的getObject方法擷取Bean,如果需要postProcess,調用BeanPostProcessor處理bean

第一步一般都是在bean已經建立過的情況下,也不算是完整的bean建立過程

  1. 在緩存中沒有擷取的bean的情況下,也就是首次建立bean的時候,判斷beanFactory是否有父級beanFactory如果有的話,交給父親beanFactory完成。
if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

           
  1. bean的建立過程開始,根據之前解析的bean的依賴,首先建立目前bean執行個體依賴的bean
if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                // 保證目前建立bean依賴的bean都已經建立了
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dependsOnBean : dependsOn) {
                        if (isDependent(beanName, dependsOnBean)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                        }
                        registerDependentBean(dependsOnBean, beanName);
                        getBean(dependsOnBean);
                    }
                }
           
  1. 建立bean執行個體,根據bean的scope執行不同的建立方式。singleton,prototype,其他的scope

4.1 我們看單例的bean建立方式。其内部調用的是createBean方法。createBean比較重要,放在下次再說

if (mbd.isSingleton()) {
              // 擷取單例,getSingleton方法内部掉的是回調中的getObject方法
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            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);
                }
           

4.2 scope為prototype類型的bean建立方式,其在調用createBean前後調用了

beforePrototypeCreation

afterPrototypeCreation

方法,也和singleton類似了。

else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
           

4.3 不同的socpe建立的bean。隻需要實作Scope接口即可。實作scope的get方法,其内部也是使用傳入的匿名工廠類getObject

else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                beforePrototypeCreation(beanName);
                                try {
                                    return createBean(beanName, mbd, args);
                                }
                                finally {
                                    afterPrototypeCreation(beanName);
                                }
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
           
  1. 判斷是否需要将bean轉換為我們指定類型的class。
// 調用函數時傳遞進來的requiredType,bean,并且bean的class類型能轉換為requiredType。然後調用TypeConverter進行轉換。
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
            try {
                return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type [" +
                            ClassUtils.getQualifiedName(requiredType) + "]", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
           
  1. 傳回bean。

最後

這次我們知道了bean的建立過程其實是在調用getBean的時候建立的。配置的scope也是在這時生效的。