springboot源碼分析一

springboot是以spring為基礎的,所以本文的大部分內(nèi)容還是在分析spring瑞信,只不過是在spring boot的場景下分析。關于spring boot的自動化裝配我們會在下一篇文章分析穴豫。本文分為三個部分喧伞,通過閱讀spring boot源碼和參閱了大量其他的文章,耗時兩個禮拜绩郎,才總結出來潘鲫。因為spring的源碼篇幅巨大、設計思想很多肋杖,基本是java程序員必須掌握的技能溉仑,所以無論花費多大的時間精力去分析都是值得的。

  • 第一部分:基本概念:一些通用的東西
  • 第二部分:bean生命周期
  • 第三部分:源碼分析
    本文源碼分析基于springboot版本為2.1.3状植,對應的spring版本為5.1.5
    了解一二兩個部分對spring的整個源碼分析會有很大的幫助浊竟。至于源碼分析部門還是建議大家自已去debug一遍。因為我的源碼分析部分沒有辦法做到非常詳盡津畸。

Part 1 基本概念

1.1 必須知道的接口振定、類

1.1.1 Aware

  • 源碼注釋
A marker superinterface indicating that a bean is eligible to be notified by the Spring container of a particular framework object through a callback-style method.
  • 翻譯
    一個超級接口,指示一個bean可以被spring 容器通過回調(diào)的方式通知肉拓。
    比如要在Bean中獲取它自已的BeanFactory, 那自定義的Bean實現(xiàn)BeanFactoryAware接口就可以了后频,BeanFactoryAware.setBeanFactory會在bean初始化之前被容器調(diào)用
public interface BeanFactoryAware extends Aware {
    void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
  • 大白話
    使Bean可以具備獲取容器資源的能力

1.1.2 BeanFactoryPostProcessor

  • 接口聲明
@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
  • 源碼注釋
 Allows for custom modification of an application context's bean definitions, adapting the bean property values of the context's underlying bean factory.
  • 翻譯
    BeanFactory的后置處理器∨荆可以在Bean創(chuàng)建之前卑惜,BeanDefinition創(chuàng)建之后,去修改BeanDefinition(甚至可以修改Bean的屬性值)驻售。但是不建議直接修改bean的值露久,修改BeanDefinition的屬性是可以的。為什么不建議在這里修改Bean的一些屬性欺栗?如果要修改那么肯定需要獲取bean毫痕,一旦執(zhí)行獲取操作,不存在就會創(chuàng)建bean迟几。但是在這個階段很多bean的PostProcessor還沒有注冊消请。那么(1)會導致bean的一些后置處理器不會執(zhí)行(比如你自已定義的)(2)會導致bean的一些屬性沒有自動注入,因為自動注入(@autowire)也是通過bean的PostProcessor完成的瘤旨。所以除非你確定你在做什么梯啤,所以不要在這里去執(zhí)行獲取bean操作。
  • 大白話
    任何Bean實現(xiàn)BeanFactoryPostProcessor接口存哲,會被容器掃描到因宇,postProcessBeanFactory會被調(diào)用七婴。

1.1.3 BeanPostProcessor

  • 接口聲明
public interface BeanPostProcessor {
 // Bean 初始化回調(diào)之前被調(diào)用
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
// Bean 初始化回調(diào)后被調(diào)用
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

何為Bean的初始化回調(diào)?InitializingBean的afterPropertiesSet 和自定義的init-method

  • 源碼注釋
Factory hook that allows for custom modification of new bean instances
  • 翻譯
    Bean的后置處理器察滑〈蚶澹可以修改bean實例。再強調(diào)一句贺辰,不要在BeanFactoryPostProcessor的實現(xiàn)里去獲取bean和修改bean

1.1.4 BeanDefinition

  • 解釋
    BeanDefinition是bean在spring中的描述(比如bean的有那些屬性户盯,值是什么,有那些注解等元信息)饲化,有了BeanDefinition我們就可以創(chuàng)建Bean莽鸭。注意BeanDefinition和Bean區(qū)別。特別是在我們和別人討論或者看別人的分析的時候吃靠,要清楚我們在討論的是BeanDefinition還是bean硫眨。BeanDefinition就相當于我們定義的類,bean就相當于我們實例的對象巢块。
  • BeanDefinition具體的實現(xiàn)類如下


    image.png
  • BeanDefinition各個實現(xiàn)的具體應用場景
    BeanDefinition有很多的子實現(xiàn)礁阁,不同的子實現(xiàn)應用不同的場景。網(wǎng)上有很多的總結族奢,但是我不知道是不是因為版本的問題姥闭,我debug出來的結果和他們的有些不同。比如說AnnotatedGenericBeanDefinition表示@Configuration注解注釋的類越走,但是我debug出來的結果是只要是通過.class文件掃描出來的bean棚品,哪怕是@Configuration注解的也是用的ScannedGenericBeanDefinition。所以大家注意區(qū)分弥姻,重點關注源碼上面的注釋部分(盡管很多注釋的地方南片,讀了也不知道說的什么,但有比沒有好)
  1. RootBeanDefinition
    直接解讀官方的注釋
// 在運行時root bean表示一個merge bean(存在父子關系庭敦,所以需要合并,關于MergedBeanDefinition下面有解釋)
 * A root bean definition represents the merged bean definition that backs
 * a specific bean in a Spring BeanFactory at runtime. 
//可以用來創(chuàng)建具有繼承關系的bean
 * It might have been created
 * from multiple original bean definitions that inherit from each other,
 * typically registered as {@link GenericBeanDefinition GenericBeanDefinitions}.
// RootBeanDefinition在運行時是bean的一個統(tǒng)一的定義薪缆,那么本身不是用RootBeanDefinition 定義秧廉,也會創(chuàng)建一個新的RootBeanDefinition。AbstractBeanFactory 中就專門創(chuàng)建了一個對象mergedBeanDefinitions用來存放拣帽,并且和DefaultListableBeanFactory中beanDefinitionMap的大小相等疼电。
 * A root bean definition is essentially the 'unified' bean definition view at runtime.
 *
// RootBeanDefinition可以用來創(chuàng)建自定義的BeanDefinition
 * <p>Root bean definitions may also be used for registering individual bean definitions
 * in the configuration phase. However,
// 從Spring 2.5開始推薦使用GenericBeanDefinition,為什么我們下面講
* since Spring 2.5, the preferred way to register
 * bean definitions programmatically is the {@link GenericBeanDefinition} class.
// GenericBeanDefinition 允許動態(tài)的定義父BeanDefinition(這里的動態(tài)不知道什么意思减拭,在源碼中沒有發(fā)現(xiàn)在上面地方使用這個動態(tài))蔽豺,不像RootBeanDefinition是硬編碼的
 * GenericBeanDefinition has the advantage that it allows to dynamically define
 * parent dependencies, not 'hard-coding' the role as a root bean definition.
 *
  1. ChildBeanDefinition
    可以從父BeanDefinition繼續(xù)屬性,通過構造函數(shù)或者setParentName可以設置父BeanDefinition
  2. GenericBeanDefinition
    GenericBeanDefinition是官方推薦的BeanDefinition拧粪,因為GenericBeanDefinition一個類就可以替代RootBeanDefinition和ChildBeanDefinition的修陡。主要是因為GenericBeanDefinition可以直接設置父BeanDefinition沧侥。個人感覺也沒啥。我們看下源碼中注解
/**
// 一站式商店魄鸦,可以構造參數(shù)宴杀、屬性值(MutablePropertyValues)
 * GenericBeanDefinition is a one-stop shop for standard bean definition purposes.
 * Like any bean definition, it allows for specifying a class plus optionally
 * constructor argument values and property values. Additionally, deriving from a
 * parent bean definition can be flexibly configured through the "parentName" property.
 *
// 用GenericBeanDefinition注冊用戶可見的bean definitions。用戶可見的意思就是可以在后置處理器中獲取
 * <p>In general, use this {@code GenericBeanDefinition} class for the purpose of
 * registering user-visible bean definitions (which a post-processor might operate on,
 * potentially even reconfiguring the parent name). Use {@code RootBeanDefinition} /
 * {@code ChildBeanDefinition} where parent/child relationships happen to be pre-determined.
 *

總的來說拾因,就是推薦使用GenericBeanDefinition

  1. ConfigurationClassBeanDefinition
    /**特指從configuration class中創(chuàng)建的bean definition
     * {@link RootBeanDefinition} marker subclass used to signify that a bean definition
     * was created from a configuration class as opposed to any other configuration source.
     * Used in bean overriding cases where it's necessary to determine whether the bean
     * definition was created externally.
     */

一般就是指用@Bean注解的bean

  1. AnnotatedGenericBeanDefinition
    springboot的啟動類的bean表述是用該類定義的旺罢。類中有一個重要的屬性AnnotationMetadata可以用來獲取bean的所有的注解信息
  2. ScannedGenericBeanDefinition
    springboot是從啟動來開始來掃描bean且是通過掃描.class文件的方式掃描的,所以除了啟動類意外绢记,所有的有@Component(包括@Configuaration, @service, @Controller)注解的bean都是包裝成ScannedGenericBeanDefinition的, 但是@Bean注解的bean不是
  3. MergedBeanDefinition
    其實spring中并沒有該類的具體定義扁达,但是源碼中又存在像getMergedBeanDefinition方法和MergedBeanDefinitionPostProcessor這個bean級別的后置處理器。其實在spring中MergedBeanDefinition對應的具體類是RootBeanDefinition蠢熄。那么什么是MergedBeanDefinition罩驻?MergedBeanDefinition又是在springboot源碼中什么時候處理的
  • 什么是MergedBeanDefinition
    MergedBeanDefinition表示將存在父子關系的bean的合并,也就是說你可以定義個一對存在繼承關系的bean护赊。spring會在某個時候?qū)⑵浜喜ⅲ▽⒏竍ean的屬性拷貝一份到子bean)
  • MergedBeanDefinition的merge發(fā)生在那里
    在執(zhí)行BeanDefinitionRegistryPostProcessor(發(fā)現(xiàn)bean惠遏,注冊BeanDefinition)之前。springboot是通過如下代碼去容器中查找BeanDefinitionRegistryPostProcessor后置處理器的
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false)

合并BeanDefinition就是在DefaultListableBeanFactory.getBeanNamesForType方法中

1.1.5 ConfigurationClassPostProcessor

用于處理啟動配置類骏啰,@SpringBootApplication中存在@Configuration注解

{@link BeanFactoryPostProcessor} used for bootstrapping processing of
 {@link Configuration @Configuration} classes.

首先這是一個實現(xiàn)了BeanFactoryPostProcessor的后置處理器节吮,而且還是實現(xiàn)了BeanDefinitionRegistryPostProcessor的后置處理器。spring的bean掃描判耕、注冊透绩、自動配置等一切功能都由ConfigurationClassPostProcessor開始

1.2 Full 模式和Lite模式

此部分參考了 Spring的@Configuration配置類-Full和Lite模式,并結合了自已的源碼分析

Full 模式和Lite模式是針對spring中的bean而言的壁熄,在ConfigurationClassUtils.checkConfigurationClassCandidate方法中有關于是Full 還Lite模式的判斷

if (isFullConfigurationCandidate(metadata)) {       beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
        }
else if (isLiteConfigurationCandidate(metadata)) {      beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
        }

1.2.1 Full模式和Lite模式的定義

官方定義為:
類上有@Configuration注解的就是Full模式帚豪。
類上沒有@Configuration注解,但是里面有@Bean方法就稱為Lite模式草丧。
透過源碼再看這個定義是不完全正確的狸臣,而應該是有如下case均認為是Lite模式的配置類:

  1. 類上標注有@Component注解(包含@Service、@Controller)
  2. 類上標注有@ComponentScan注解
  3. 類上標注有@Import注解
  4. 類上標注有@ImportResource注解
  5. 若類上沒有任何注解昌执,但類內(nèi)存在@Bean方法

以上case的前提均是類上沒有被標注@Configuration烛亦,在Spring 5.2之后新增了一種case也算作Lite模式:標注有@Configuration(proxyBeanMethods = false),注意:此值默認是true哦懂拾,需要顯示改為false才算是Lite模式
細心的你會發(fā)現(xiàn)煤禽,自Spring5.2(對應Spring Boot 2.2.0)開始,內(nèi)置的幾乎所有的@Configuration配置類都被修改為了@Configuration(proxyBeanMethods = false)岖赋,目的何為檬果?答:以此來降低啟動時間,為Cloud Native繼續(xù)做準備。

1.2.2 Full模式和Lite模式的不同

Full模式下:配置類會被CGLIB增強(生成代理對象)选脊,放進IoC容器內(nèi)的是代理
Lite模式下:放進IoC容器內(nèi)的是類的實例杭抠,沒有代理
代理的好處就是我們可以在方法的前后做一些其他的事情(AOP思想)

1.2.3 為什么需要Full模式和Lite模式

假設已經(jīng)存在Persion類,請思考下面兩段代碼中的persion1和persion2是不是相等的(是不是同一個對象)

@Configuration
public class MainConfiguration{
    @Bean("persion1")
    public Persion persion1() {
        return new Persion("payne");
    }
    @Bean("persion2")
    public Persion persion2() {
        return persion1();
    }
}
@Component
public class MainConfiguration{
    @Bean("persion1")
    public Persion persion1() {
        return new Persion("payne");
    }
    @Bean("persion2")
    public Persion persion2() {
        return persion1();
    }
}

在Full模型下知牌,也就是代碼片段一祈争。persion1和persion2是相等的,盡管在persion2()方法中調(diào)用了persion1()方法角寸。persion1()中每次是new 一個Persion的
在Lite模式下菩混,也就是代碼片段二,persion1和persion2是不相等的扁藕。
如果沒有代理對象沮峡,我們是做不到代碼一中的效果的。

Part 2 Bean生命周期

spring bean 的生命周期在BeanFactory接口注釋中有完整的描述亿柑。分為兩個部分邢疙,第一部分是bean可使用之前的部分,第二部分為shutdown bean factory之后的

// 第一部分
* <p>Bean factory implementations should support the standard bean lifecycle interfaces
 * as far as possible. The full set of initialization methods and their standard order is:
 * <ol>
 * <li>BeanNameAware's {@code setBeanName}
 * <li>BeanClassLoaderAware's {@code setBeanClassLoader}
 * <li>BeanFactoryAware's {@code setBeanFactory}
 * <li>EnvironmentAware's {@code setEnvironment}
 * <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
 * <li>ResourceLoaderAware's {@code setResourceLoader}
 * (only applicable when running in an application context)
 * <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
 * (only applicable when running in an application context)
 * <li>MessageSourceAware's {@code setMessageSource}
 * (only applicable when running in an application context)
 * <li>ApplicationContextAware's {@code setApplicationContext}
 * (only applicable when running in an application context)
 * <li>ServletContextAware's {@code setServletContext}
 * (only applicable when running in a web application context)
 * <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
 * <li>InitializingBean's {@code afterPropertiesSet}
 * <li>a custom init-method definition
 * <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
 * </ol>
 *
//第二部分
 * <p>On shutdown of a bean factory, the following lifecycle methods apply:
 * <ol>
 * <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
 * <li>DisposableBean's {@code destroy}
 * <li>a custom destroy-method definition
 * </ol>

整理如下:
第一部分

  1. BeanNameAware.setBeanName
  2. BeanClassLoaderAware.setBeanClassLoader
  3. BeanFactoryAware.setBeanFactory
  4. EnvironmentAware.setEnvironment
  5. EmbeddedValueResolverAware.setEmbeddedValueResolver
  6. ResourceLoaderAware.setResourceLoader
  7. ApplicationEventPublisherAware.setApplicationEventPublisher
  8. MessageSourceAware.setMessageSource
  9. ApplicationContextAware.setApplicationContext
  10. ServletContextAware.setServletContext
  11. BeanPostProcessors.postProcessBeforeInitialization
  12. InitializingBean.afterPropertiesSet
  13. a custom init-method definition
  14. BeanPostProcessors.postProcessAfterInitialization
    以上生命周期是按發(fā)生的順序排序的望薄,最早的生命周期BeanNameAware.setBeanName也是發(fā)生在bean實例化疟游、填充屬性之后的,此時的bean已經(jīng)是一個完整的對象了痕支,已經(jīng)是可用狀態(tài)颁虐。
    借用參考文獻一的圖如下:
    image.png

第二部分

  1. DestructionAwareBeanPostProcessors.postProcessBeforeDestruction
  2. DisposableBean.destroy
  3. a custom destroy-method definition

bean更完整的生命周期

但是以上的上面周期僅僅是我們自已定義的bean能看到的生命周期,那spring 本身一些bean的生命周期是沒有包含在這里面的卧须。很久之前寫過一篇通過xml注冊bean的生命周期文章中總結過一個完整的圖另绩,在這里同樣適用,因為spring的bean生命周期是一樣的花嘶。大家也可以再看一下這篇文章前面總結的一些概念spring bean 生命周期笋籽。我們再把圖搬過來一下

完整的bean生命周期

這個圖第一行BeanDefinitionRegistryPostProcessor的實例化就是指的我們在1.1.5節(jié)提到的ConfigurationClassPostProcessor。重要的事情多提幾遍ConfigurationClassPostProcessor是spring boot中IOC的起點椭员。

Part 3 源碼分析

源碼分析部分车海,我會在我認為重要的地方寫上注釋,也會去掉一些我任認為不重要的地方拆撼。
目錄的編號對應注釋前面的編號
springboot的代碼篇幅比較大容劳。我們暫且分為三個大的部分

    1. 啟動初始化部分
    1. bean掃描部分
    1. bean的實例化部分

啟動初始化部分

3.1、SpringApplication.run方法

public ConfigurableApplicationContext run(String... args) {
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
//(1)添加一些基本的類型轉(zhuǎn)換器(2)配置環(huán)境(1闸度、配置文件,2蚜印、激活了那個profile(3)占位符等(@value注解的占位符))
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            configureIgnoreBeanInfo(environment);
//打印springboot的banner
            Banner printedBanner = printBanner(environment);
//創(chuàng)建ApplicationContent, (1)DefaultListableBeanFactory也在這里創(chuàng)建 (2) 這里有一個非常重要的BeanFactoryPostProcessor:ConfigurationClassPostProcessor在這里面注冊
            context = createApplicationContext();
            exceptionReporters = getSpringFactoriesInstances(
                    SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
//(3)加載primarySources(其實就是我們的啟動類)莺禁,將其注冊為一個bean(bean的注冊指創(chuàng)建一個BeanDefinition,然后放到beanDefinitionMap對象中窄赋,并沒有完成實例化)
            prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
//(4) 最復雜哟冬,關鍵的地方楼熄,下面詳細講解
            refreshContext(context);
// (5)當ApplicationContent refresh 后,執(zhí)行該方法浩峡,這里是一個空的實現(xiàn)
            afterRefresh(context, applicationArguments);
            stopWatch.stop();
            listeners.started(context);
            callRunners(context, applicationArguments);
            listeners.running(context);
        return context;
    }

3.1.4 springApplication.refreshContext詳解

springApplication.refreshContext方法實際調(diào)用的是AbstractApplicationContext.refresh()方法可岂。下面直接看該方法

public void refresh() throws BeansException, IllegalStateException {

            // (1)無重要內(nèi)容,主要設置啟動時間翰灾,激活標志
            prepareRefresh();

            // (2)無重要內(nèi)容缕粹,獲取bean factory(實際類型為DefaultListableBeanFactory在上面已經(jīng)創(chuàng)建過了)
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // (3)添加了兩個重要的BeanPostProcessor,(1)ApplicationContextAwareProcessor纸淮,bean生命周期關于Aware部分的就是通過添加該bean post processor 實現(xiàn) (2)ApplicationListenerDetector平斩,關于事件監(jiān)聽(發(fā)布-訂閱者模式)是通過該bean post processor 實現(xiàn)的(3)添加了3個bean(environment, systemProperties咽块,systemEnvironment)看名字就知道是關于系統(tǒng)一些變量的
            prepareBeanFactory(beanFactory);

                // (4)無具體實現(xiàn)绘面,其他content可以重寫改方法
                postProcessBeanFactory(beanFactory);

                // (5)調(diào)用一些已經(jīng)注冊為bean的BeanFactoryPostProcessor,還記的創(chuàng)建content時候我們提到的那個 重要的ConfigurationClassPostProcessor類嗎侈沪?
                invokeBeanFactoryPostProcessors(beanFactory);

                // (6)Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                //(7)國際化相關處理

                initMessageSource();

                //(8) 事件通知機制揭璃,發(fā)布訂閱者實現(xiàn)
                initApplicationEventMulticaster();

                // (9)其他的上下文比如web應用等可以實現(xiàn)改方法,用來實例化一些特殊的bean
                onRefresh();

                // (10)事件通知機制亭罪,注冊事件
                registerListeners();

                // (11)我們在invokeBeanFactoryPostProcessors中掃描到了很對的bean瘦馍,我們執(zhí)行將其BeanDefinition注冊到容器中,但是還沒有實例化皆撩,那么實例化就在finishBeanFactoryInitialization中實例化扣墩。包括BeanPostProcessor的執(zhí)行
                finishBeanFactoryInitialization(beanFactory);

                // (12)Last step: publish corresponding event.
                finishRefresh();
            
    }

3.2 bean的掃描部分

3.2.1 invokeBeanFactoryPostProcessors

    /**
     * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
     * respecting explicit order if given.
     * <p>Must be called before singleton instantiation.
     */

該方法的注釋寫的很明白,實例化并且調(diào)用注冊為bean的BeanFactoryPostProcessor扛吞,這里面會調(diào)用我們在createApplicationContext方法中注冊為bean的ConfigurationClassPostProcessor對象呻惕,該對象是是一個BeanFactoryPostProcessor。試想一下spring boot是如何找到我們定義的bean的呢滥比?其他就是通過ConfigurationClassPostProcessor

public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // 后置處理器已經(jīng)執(zhí)行過的bean亚脆,防止執(zhí)行多次
        Set<String> processedBeans = new HashSet<>();
// 將后置處理器分類,具體的見代碼下面的解釋
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
//(1) 執(zhí)行invokeBeanDefinitionRegistryPostProcessors                  registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }

// 見下面解釋
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // 獲取BeanDefinitionRegistryPostProcessor的bean名稱盲泛,實際上注冊為bean且類型是BeanDefinitionRegistryPostProcessor的類就是ConfigurationClassPostProcessor濒持,且只有這一個
            String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
// ConfigurationClassPostProcessor是實現(xiàn)了PriorityOrdered接口的
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//beanFactory.getBean 當bean沒有實例化的時候,會實例化寺滚,所以ConfigurationClassPostProcessor之前只是一個BeanDefinition,在這里會實例化
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
// (1)這里才是正式的ConfigurationClassPostProcessor柑营, 會將所有滿足bean條件的BeanDefinition注冊 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // 獲取BeanDefinitionRegistryPostProcessors 類型的bean 并且實現(xiàn) Ordered接口
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
// (1)再次執(zhí)行BeanFactoryPostProcessors, 注意如果上面已經(jīng)執(zhí)行過了,則不再執(zhí)行         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // 在執(zhí)行上面后置處理器的過程中村视,會掃描到一些新的后置處理器官套,那么也要執(zhí)行
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
//(1) 執(zhí)行invokeBeanDefinitionRegistryPostProcessors                  invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            // (2)之前注冊過一個重要的BeanFactoryPostProcessor: ConfigurationClassPostProcessor在這里會被調(diào)用,如果Bean是Full 模式的,那么cglib生成代理類放到beanDefinitionMap中

            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // 在掃描的過程中會發(fā)現(xiàn)新的實現(xiàn)BeanFactoryPostProcessor的bean奶赔,不如我們自已實現(xiàn)的一些后置處理器
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // 實現(xiàn) PriorityOrdered的后置處理器先執(zhí)行
        // 實現(xiàn)Ordered的后置處理其次, 最后是其他的后置處理器
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
//(2)執(zhí)行invokeBeanFactoryPostProcessors
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
//(2)執(zhí)行invokeBeanFactoryPostProcessors      
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
//(2)執(zhí)行invokeBeanFactoryPostProcessors
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }

總結

(1)方法中有三個主要的對象:

  1. regularPostProcessors:普通的后置處理器惋嚎,只實現(xiàn)BeanFactoryPostProcessor接口
  2. registryProcessors:除了實現(xiàn)BeanFactoryPostProcessor還實現(xiàn)BeanDefinitionRegistryPostProcessor的后置處理器
  3. currentRegistryProcessors:在容器中注冊為bean且類型是BeanDefinitionRegistryPostProcessor的后置處理器(注意并發(fā)所有的后置處理器都會注冊為bean),這里只有ConfigurationClassPostProcessor是滿足條件的

上面對象中的后置處理器都執(zhí)行完了站刑,才會執(zhí)行我們自已定義的后置處理器和我們再掃描過程中發(fā)現(xiàn)的后置處理器另伍,我們經(jīng)常使用@value("${變量名稱}")來填充屬性值就是通過在這里掃描到的PropertySourcesPlaceholderConfigurer這個后置處理器實現(xiàn)的

(2)執(zhí)行順序

  1. currentRegistryProcessors中實現(xiàn)PriorityOrdered的后置處理器最先執(zhí)行
  2. currentRegistryProcessors中實現(xiàn)Ordered的后置處理器其次
  3. registryProcessors中的后置處理器
  4. regularPostProcessors中的后置處理器最后
  5. 我們自已在代碼注冊的后置處理器(就是通過ConfigurationClassPostProcessor才讓容器發(fā)現(xiàn)我們自已定義的后置處理器的,所以肯定是最后執(zhí)行)

兩條原則

1. 先執(zhí)行實現(xiàn)BeanDefinitionRegistryPostProcessor的后置處理器绞旅,后執(zhí)行實現(xiàn)BeanFactoryPostProcessor的限制性(注意執(zhí)行的方法不一樣)

2. 實現(xiàn)PriorityOrdered的后置處理器先執(zhí)行摆尝,實現(xiàn)Ordered的后執(zhí)行

結合代碼來說就是BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry先執(zhí)行,BeanFactoryPostProcessor.postProcessBeanFactory后執(zhí)行玻靡。BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor實現(xiàn)類结榄,所以ConfigurationClassPostProcessor先執(zhí)行postProcessBeanDefinitionRegistry來注冊BeanDefinition,然后執(zhí)行postProcessBeanFactory將Full模式的bean class用cglib生成代理類放到beanDefinitionMap中

3.2.1.1 invokeBeanDefinitionRegistryPostProcessors

    private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
// 調(diào)用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry  
        postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }

postProcessBeanDefinitionRegistry實際處理邏輯在processConfigBeanDefinitions中
ConfigurationClassPostProcessor.processConfigBeanDefinitions處理邏輯

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 獲取當前content所有的BeanDefinition(沒有實例化的bean)
        String[] candidateNames = registry.getBeanDefinitionNames();

        for (String beanName : candidateNames) {
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//(1)關于Full模式和life模式參見文章末尾囤捻,這里主要是找出聲明了注解@Configuration或者@Component的類(注意像@Service臼朗,@Controller等存在嵌套的元注解@Component也是滿足這里的條件的)
            if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                    ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
// (2) 判斷該類有沒有可能是configuration 類
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }

// 由于springboot的啟動類上是有@SpringBootApplication注解的,該注解是存在@Configuration嵌套注解的蝎土,所以啟動類肯定是滿足這個條件的configCandidates里面最起碼是存在啟動類的這個對象的
        if (configCandidates.isEmpty()) {
            return;
        }
// 創(chuàng)建一個@Configuration class解析類
        // Parse each @Configuration class
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this.componentScanBeanNameGenerator, registry);

        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
//(4)注意這里是一個循環(huán)视哑,正常情況下,這里的candidates里面只有一個springboot啟動類誊涯,所以該循環(huán)的作用就是如果在掃描啟動類的過程又碰到新的@Configuration class那么一直掃描下去挡毅,知道找出所有的@Configuration class,掃描完了其實Bean也就掃描完了
        do {
            parser.parse(candidates);
            parser.validate();

            Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
            configClasses.removeAll(alreadyParsed);

            // Read the model and create bean definitions based on its content
            if (this.reader == null) {
                this.reader = new ConfigurationClassBeanDefinitionReader(
                        registry, this.sourceExtractor, this.resourceLoader, this.environment,
                        this.importBeanNameGenerator, parser.getImportRegistry());
            }
//(5)Configuration class 中的@Bean 方法還沒有注冊BeanDefinition, 下面會注冊(掃描@Import注解時暴构,也會出現(xiàn)新的Configuration class(自動配置))
            this.reader.loadBeanDefinitions(configClasses);
            alreadyParsed.addAll(configClasses);

            candidates.clear();
// 在掃描到的Configuration class中也是有@Component注解的跪呈,那么循環(huán)的掃描
            if (registry.getBeanDefinitionCount() > candidateNames.length) {
                String[] newCandidateNames = registry.getBeanDefinitionNames();
                Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                Set<String> alreadyParsedClasses = new HashSet<>();
                for (ConfigurationClass configurationClass : alreadyParsed) {
                    alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                }
                for (String candidateName : newCandidateNames) {
                    if (!oldCandidateNames.contains(candidateName)) {
                        BeanDefinition bd = registry.getBeanDefinition(candidateName);
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                                !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                            candidates.add(new BeanDefinitionHolder(bd, candidateName));
                        }
                    }
                }
                candidateNames = newCandidateNames;
            }
        }
        while (!candidates.isEmpty());

        // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
        if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
            sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
        }

        if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
            // Clear cache in externally provided MetadataReaderFactory; this is a no-op
            // for a shared cache since it'll be cleared by the ApplicationContext.
            ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
        }
    }

parse的調(diào)用鏈比較長,跳過無關的方法取逾,掃描的核心邏輯在下面的方法中

3.2.1.1.4 ConfigurationClassParser.doProcessConfigurationClass
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
            throws IOException {
//如果該ConfigurationClass存在成員內(nèi)部類耗绿,那么遞歸的掃描該類
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            // Recursively process any member (nested) classes first
            processMemberClasses(configClass, sourceClass);
        }

        // 處理@PropertySource注解
        for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), PropertySources.class,
                org.springframework.context.annotation.PropertySource.class)) {
            if (this.environment instanceof ConfigurableEnvironment) {
                processPropertySource(propertySource);
            }
            else {
                logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                        "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }

        // 處理@ComponentScan 注解,ComponentScan會掃描我們啟動類所在包下面所有的class文件砾隅,將所有有@Component注解的class會封裝成BeanDefinition注冊到容器中
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty() &&
                !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            for (AnnotationAttributes componentScan : componentScans) {
                // The config class is annotated with @ComponentScan -> perform the scan immediately
                Set<BeanDefinitionHolder> scannedBeanDefinitions =
                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                // 遞歸的掃描上面掃描到的scannedBeanDefinitions误阻,如果該class上還有@PropertySource,@ComponentScan等注解就一直遞歸的處理
                for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

        // 處理@Import 注解, @SpringBootApplication的復合注解@EnableAutoConfiguration中存在@Import(AutoConfigurationImportSelector.class)晴埂,springboot中的自動配置就是在這里通過這個注解實現(xiàn)的
        processImports(configClass, sourceClass, getImports(sourceClass), true);

        // 處理 @ImportResource 注解
        AnnotationAttributes importResource =
                AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        if (importResource != null) {
            String[] resources = importResource.getStringArray("locations");
            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
            for (String resource : resources) {
                String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                configClass.addImportedResource(resolvedResource, readerClass);
            }
        }

        // 處理 @Bean注解的 方法
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }

        // 處理接口的默認方法
        processInterfaces(configClass, sourceClass);

        // 處理父類 superclass
        if (sourceClass.getMetadata().hasSuperClass()) {
            String superclass = sourceClass.getMetadata().getSuperClassName();
            if (superclass != null && !superclass.startsWith("java") &&
                    !this.knownSuperclasses.containsKey(superclass)) {
                this.knownSuperclasses.put(superclass, configClass);
                // Superclass found, return its annotation metadata and recurse
                return sourceClass.getSuperClass();
            }
        }

        // No superclass -> processing is complete
        return null;
    }

總結一下究反,方法的參數(shù)ConfigurationClass就是我們的啟動的封裝類,所以掃描就是從我們的啟動類開始掃描的
(1) 方法作用
遞歸的掃描滿足條件的Bean將其封裝成BeanDefinition注冊到容器上下文中儒洛。遞歸是從ConfigurationClass開始的精耐,那么ConfigurationClass是如何定義的呢?通過如下方法判斷琅锻。

ConfigurationClassUtils.checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory)

總結一下就是:如果類上面有@Component注解就是ConfigurationClassCandidate黍氮,因為@Configuration,@Service,@Controller等注解的元注解也是包含@Component的所以有這些注解的類也是ConfigurationClassCandidate唐含。特別浅浮,如果類上沒有注解但是沫浆,存在@Bean方法注解,那么該類也是ConfigurationClassCandidate

(2)掃描循序
掃描過程中只要碰到ConfigurationClassCandidate就遞歸掃描滚秩,碰到bean就將其BeanDefinition注冊到容器中

  1. 成員內(nèi)部類
  2. @PropertySource注解
  3. @ComponentScan注解
  4. @Import注解
  5. @ImportResource注解
  6. 內(nèi)部@Bean方法
  7. 接口默認方法
  8. 父類

3.3 bean的注冊部分

bean的注冊主要實現(xiàn)在refresh方法的finishBeanFactoryInitialization

finishBeanFactoryInitialization詳解

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // 設置凍結BeanDefinition的flag专执,不希望在注冊實例的時候改變bean的定義了
        beanFactory.freezeConfiguration();
      // (1)實例化剩下的非lazy的bean,有些bean比如自已定義的BeanPostProcessor還有容器的一些bean在之前已經(jīng)實例化過了郁油,所以這里實現(xiàn)剩下的本股,我們自已代碼中很多就是這里實例化
        // Instantiate all remaining (non-lazy-init) singletons.
        beanFactory.preInstantiateSingletons();

3.3.1 preInstantiateSingletons

    public void preInstantiateSingletons() throws BeansException {
// beanDefinitionNames 存放所有的之前掃描到的BeanDefinition
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 遍歷所有的BeanDefinition,創(chuàng)建bean
        for (String beanName : beanNames) {
// MergedBeanDefinition 之前已經(jīng)詳細說過概念桐腌,合并具有繼承關系的BeanDefinition
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 工程bean的處理
                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 {
// (1)獲取bean拄显,獲取不到則創(chuàng)建
                    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();
                }
            }
        }
    }

3.3.1.1 doCreateBean

跳過不重要的調(diào)用關系直接看doCreateBean

    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) {
// 創(chuàng)建bean實例
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = instanceWrapper.getWrappedInstance();
        

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
//填充bean屬性,@autowire字段的屬性就是在這里填充的案站,通過AutowiredAnnotationBeanPostProcessor這個后置處理器
            populateBean(beanName, mbd, instanceWrapper);
// (1)初始化回調(diào)
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {  
        }
        }

        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

3.3.1.1.1 initializeBean

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// bean生命周期與Aware相關的在這里調(diào)用       
        invokeAwareMethods(beanName, bean);
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
// 初始化回調(diào)前置操作
            wrappedBean = 
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
// 初始化回調(diào)
        invokeInitMethods(beanName, wrappedBean, mbd);
// 初始化回調(diào)后置操作
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = 
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

參考文獻

  1. Spring – Bean Life Cycle
  2. Spring源碼分析之BeanFactoryPostProcessor調(diào)用過程詳解
  3. Spring的@Configuration配置類-Full和Lite模式
  4. 深入理解SpringBoot的過濾條件--AutoConfigure
  5. EnableAutoConfiguration注解的工作原理
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末躬审,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蟆盐,更是在濱河造成了極大的恐慌承边,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件石挂,死亡現(xiàn)場離奇詭異博助,居然都是意外死亡,警方通過查閱死者的電腦和手機痹愚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門富岳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拯腮,你說我怎么就攤上這事窖式。” “怎么了疾瓮?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵脖镀,是天一觀的道長。 經(jīng)常有香客問我狼电,道長蜒灰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任肩碟,我火速辦了婚禮强窖,結果婚禮上,老公的妹妹穿的比我還像新娘削祈。我一直安慰自己翅溺,他們只是感情好脑漫,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著咙崎,像睡著了一般优幸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上褪猛,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天网杆,我揣著相機與錄音,去河邊找鬼伊滋。 笑死碳却,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的笑旺。 我是一名探鬼主播昼浦,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼筒主!你這毒婦竟也來了关噪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤物舒,失蹤者是張志新(化名)和其女友劉穎色洞,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冠胯,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡火诸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了荠察。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片置蜀。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖悉盆,靈堂內(nèi)的尸體忽然破棺而出盯荤,到底是詐尸還是另有隱情,我是刑警寧澤焕盟,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布秋秤,位于F島的核電站,受9級特大地震影響脚翘,放射性物質(zhì)發(fā)生泄漏灼卢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一来农、第九天 我趴在偏房一處隱蔽的房頂上張望鞋真。 院中可真熱鬧,春花似錦沃于、人聲如沸涩咖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽檩互。三九已至特幔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盾似,已是汗流浹背敬辣。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留零院,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓村刨,卻偏偏與公主長得像告抄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嵌牺,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容