SpringBoot IOC生命週期源碼分析

JDK:1.8

SpringBoot:2.1.5

把整個過程總結在前面:

搭建源碼閱讀環境

這裏你也可以不用搭建,直接使用Idea的源碼下載功能也可以,但這樣拿到的源碼是隻讀的,如果你想在閱讀過的地方加上註釋則很困難。另外我們搭建的是Springboot的源碼閱讀環境,並不是Spring-framework的,前者是基於maven構建的項目,後者是基於gradle,兩者搭建方法不一樣。

1.到github上下載源碼:https://github.com/spring-projects/spring-boot。選擇release:

找到2.1.5版本,當然你也可以選擇其他版本,這個隨意。拉到版本頁面的最底部,現在源碼:

2.下載下來後,解壓到某個位置,然後用idea打開主目錄下的pom文件,選擇open as project。首次打開項目可能會比較久,要解析許多依賴。

很多教程裏面還會教你如何安裝maven和grdle,2019版本的idea並不需要額外安裝這兩個東西,它已經自帶了。

3.項目打開之後,看到的目錄是這樣的:

設置項目的jdk版本爲java8,選擇maven選項卡,點擊那個m圖標:

輸入mvn clean install -DskipTests -Pfast

這步操作也需要挺長的時間,等maven執行完畢,這個項目已經配置了一個啓動配置,直接點擊debug就能運行起來:

4.寫一個新的maven項目作爲測試項目。選擇選擇最上層的目錄,右鍵,基於maven新添加一個module:spring-boot-study。如圖:

5.在pom文件裏面加上依賴:

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
          <version>2.1.5.RELEASE</version>
      </dependency>
2.1.5.RELAESE是通過我們下載的源碼生成的,如果你選擇其他的版本,maven會從遠程倉庫裏面下載,那麼你調試的代碼也就是不是你下載的代碼了。

你選擇的時候,idea提示器會提示你哪個版本本地就有,比如2.1.5這個版本和其他的版本標誌是不一樣的。看上圖。

6.在項目的App類裏面添加如下代碼:

@SpringBootApplication
public class App {
    public static void main(String[] args)
    {
        SpringApplication.run(App.class,args);
    }
}
這裏有個坑,原來我們創建的module,其目錄結構是繼承自主項目的,這會導致這個項目運行的時候報一個錯誤:

這個問題的解決辦法也比較簡單,只需要把原來的目錄結構刪了,重新創建一下App這個類,其目錄結構如下:

然後鼠標放到main方法內部,右鍵,Debug ‘App’,程序就能正常debug了,結果如圖:

到現在爲止,SpringBoot的源碼閱讀環境就搭建好了。現在可以在這個study模塊上寫一些測試代碼,跟蹤代碼,分析源碼了。

值得一提的是,SpringBoot這個項目大量依賴Spring Framework,因此,如果單純下載下來SpringBoot的源碼,很多代碼仍然無法跟蹤進去,這點後面我們在分析ioc源碼的時候你就會發現。

分析SpringBoot的IOC過程:

1.run方法返回值類型是ConfigurableApplicationContext,這裏的繼承關係是:

ConfigurableApplicationContext=》ApplicationContext=》ListableBeanFactory=》BeanFactory
上面列舉的全是接口,BeanFactory是最頂層的接口,spring裏面各式各樣的context,比如AnnotationConfigApplicationContext、XmlServletWebServerApplicationContext等都繼承自它。那麼這個ConfigurableApplicationContext具體是由哪個類實現的呢,持續跟蹤代碼會跟蹤到下面的方法:

  

  protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch (this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                    break;
                case REACTIVE:
                    contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                    break;
                default:
                    contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
                }
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Unable create a default ApplicationContext, "
                                + "please specify an ApplicationContextClass",
                        ex);
            }
        }
        return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
    }


這個方法實際上告訴了我們,在2.1.5版本中,總共有三種context的實現,具體使用哪一種,取決於webApplicationType,而webApplicationType則是通過掃描包裏面的依賴,根據依賴內容而得出的(是否包含web相關的依賴等)。具體怎麼得到的,由於這塊和ioc關係不大,這裏不追究了。

2持續跟蹤run方法,一直跟蹤到

refreshContext(context);
這個方法,在這個方法之前的工作都是spring相關的準備工作,和ioc關係不大,這個方法是用來實現ioc相關功能的核心方法,整個ioc的生命週期,都在這個方法裏。

3.持續跟蹤代碼,最後跟蹤到AbstractApplicationContext這個抽象類的refresh方法,這個類直接繼承自ConfigurableApplicationContext接口,該類屬於spring framework,不屬於springboot,因此如果你嘗試修改它,會發現它是隻讀的,是因爲我們並沒有把spring framework的代碼下載下來。方法的具體實現如下,這個ioc的生命週期發生的操作,都在這裏了。具體每步的功能是做什麼,官方都添加了英文註釋,但是這個註釋有些簡單,我又額外添加了一些中文註釋進來:

    

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();
 
            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
 
            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);
 
            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);
 
                // Invoke factory processors registered as beans in the context.
                //非常重要的一步,進行包掃描,把bean定義掃描出來,
                //什麼是bean定義,在spring裏面表現爲BeanDefination,
                //它用來描述bean,比如是否是單例,是否是懶加載等等信息,
                //這些信息都是從xml配置信息或者註解信息裏面讀出來。
                invokeBeanFactoryPostProcessors(beanFactory);
 
                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);
 
                // Initialize message source for this context.
                initMessageSource();
 
                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();
 
                // Initialize other special beans in specific context subclasses.
                onRefresh();
 
                // Check for listener beans and register them.
                registerListeners();
 
                // Instantiate all remaining (non-lazy-init) singletons.
                //非常重要的一步,完成bean的實例化
                finishBeanFactoryInitialization(beanFactory);
 
                // Last step: publish corresponding event.
                finishRefresh();
            }
 
            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
 
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();
 
                // Reset 'active' flag.
                cancelRefresh(ex);
 
                // Propagate exception to caller.
                throw ex;
            }
 
            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }


4.第一步掃描包,它的代碼實現在下面這個方法裏面:

invokeBeanFactoryPostProcessors(beanFactory);
掃描包的目的是把所有的bean定義掃描出來,然後放到下面這個map裏面:

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
由此可見,bean定義的緩存類型是ConcurrentHashMap類型,值的類型是BeanDefinition,它是一個接口,具體的實現有很多類,spring會根據不同的bean定義方案實現不同的類。它總共有哪些實現,看下圖:

在執行這步代碼之前,2.1.5版本的springboot裏面它的值是6,具體內容如下:

其中就包含了我們的入口類,app。

在這個方法執行完之後,會把我們定義的bean也放進來以及系統定義的bean加載進來,看下執行後它的值:

我標註的bean是我自己定義的一個測試類,其他基本都是系統自己的bean。

5.這些bean定義緩存決定了ioc容器處理bean的方案,那麼是不是意味着它只能通過配置或者註解來決定呢,答案是否定的,其實在這個過程中我們是可以干預的,干預是使用beanfactory後置處理器(注意不是bean的後置處理器)來處理的,參考下面的代碼:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        GenericBeanDefinition genericBeanDefinition=(GenericBeanDefinition)beanFactory.getBeanDefinition("singletonTest");
        genericBeanDefinition.setLazyInit(true);
    }
}
 這樣就可以把我們定義的bean設置爲懶加載了。當然了,你也可以通過在bean定義的時候加上註解實現這個功能,這倆效果是一樣的:

@Component
@Lazy
public class SingletonTest {
 
    public SingletonTest()
    {
        System.out.println("SingletonTest被實例化");
    }
    public void test()
    {
    }
}
5.包掃描結束後,後來又到了一步非常關鍵的方法:finishBeanFactoryInitialization(beanFactory)。這個方法的作用是完成非懶加載的類的單例類的實例化。

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }
 
        // Register a default embedded value resolver if no bean post-processor
        // (such as a PropertyPlaceholderConfigurer bean) registered any before:
        // at this point, primarily for resolution in annotation attribute values.
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }
 
        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }
 
        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);
 
        // Allow for caching all bean definition metadata, not expecting further changes.
        beanFactory.freezeConfiguration();
 
        // Instantiate all remaining (non-lazy-init) singletons.
        //關鍵步驟,上面的基本都是準備工作。
        beanFactory.preInstantiateSingletons();
    }
6.重點關注下preInstantiateSingletons這個方法,其代碼如下:

  

  public void preInstantiateSingletons() throws BeansException {
        if (logger.isTraceEnabled()) {
            logger.trace("Pre-instantiating singletons in " + this);
        }
 
        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
 
        // Trigger initialization of all non-lazy singleton beans...
        //實例化所有的單例的、非懶加載的、非抽象的bean。
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        final FactoryBean<?> factory = (FactoryBean<?>) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                            ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }
 
        // Trigger post-initialization callback for all applicable beans...
        //後置處理所有的後置處理方法
        for (String beanName : beanNames) {
            Object singletonInstance = getSingleton(beanName);
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }


在第一次輪詢中,做了一個判斷,判斷是否是factorybean,什麼是factorybean,參考我另一篇博文https://blog.csdn.net/dap769815768/article/details/100862413。如果不是直接通過getBean方法就可以了。

7.getBean最終會走到doGetBean方法:

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
 
        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.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 + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
 
        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            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 (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }
 
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }
 
            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);
 
                // Guarantee initialization of beans that the current bean depends on.
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName);
                        try {
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }
 
                // Create bean instance.
                //重要,真實地創建bean實例的方法。
                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);
                }
 
                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);
                }
 
                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, () -> {
                            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);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
 
        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }


這裏需要關注的是getSingleton這個方法,它是bean的實際實例化方法,包含了屬性注入的部分。

8.getSingleton方法:

    

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                //解決循環依賴問題,使用一個set保存正在實例化的bean。
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    //調用傳進來的回調createBean,創建bean。
                    singletonObject = singletonFactory.getObject();
                    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);
                }
            }
            return singletonObject;
        }
    }


首先是通過調用下面的方法,把正在實例化的bean緩存起來:

    protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }
然後調用

singletonObject = singletonFactory.getObject();
執行回調createBean(beanName, mbd, args),進入到真正的bean創建方法中。

9.createBean方法: 

   protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
 
        if (logger.isTraceEnabled()) {
            logger.trace("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;
 
        // Make sure bean class is actually resolved at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }
 
        // Prepare method overrides.
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }
 
        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }
 
        try {
            //完成創建bean,完整的bean,包括屬性注入。
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }
在doCreateBean方法,整個bean就被創建了,該方法源碼如下:

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {
 
        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //通過某個策略創建一個bean的包裝實例
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        //通過類的包裝實例獲取到類的實例,但未完成屬性注入。
        final Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }
 
        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }
 
        // 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.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }
 
        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            //完成屬性注入
            populateBean(beanName, mbd, instanceWrapper);
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }
 
        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }
 
        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }
 
        return exposedObject;
    }


 

8.循環依賴。spring中如果循環依賴的方式是構造器注入,那麼會拋出異常:The dependencies of some of the beans in the application context form a cycle。如果是屬性注入,要求兩邊不能全部是多例,否則也會拋出上面的異常。如果A是多例,B是單例,那麼不可以對A進行自動注入,否則仍然會拋出上面的異常。原因很簡單:

實例化A=》注入A的依賴B=》實例化B=》注入B的依賴A=》由於A是多例,所以不會獲取之前實例化一半的A,而是重新實例化一個A=》程序回到最初的一步,進入死循環。

而如果反過來,則沒問題:

實例化B=》注入B的依賴A=》實例化A=》注入A的依賴B=》B是單例,所以直接將之前實例化一半的B的引用傳給A=》自動注入完成。

這裏面其實就是誰先實例化的問題。多例的那個不能先實例化,必須後實例化,纔不會導致報循環依賴的異常。

原文鏈接:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章