逐行閱讀Spring5.X源碼(番外篇)AnnotatedBeanDefinitionReader的作用

? ? ? ?在上一篇文章里面我們討論了一個(gè)beanDefintion對(duì)象的重要性野建,為了討論spring當(dāng)中的beanDefinition對(duì)象我們不得不牽扯出spring當(dāng)中的bean工廠后置處理器也就是BeanFactoryPostProcessor這個(gè)類(lèi);繼而討論了BeanFactoryPostProcessor的大概執(zhí)行時(shí)機(jī)(BeanFactoryPostProcessor的執(zhí)行時(shí)機(jī)很重要而且spring內(nèi)部做的稍微有點(diǎn)復(fù)雜恬叹,本文重點(diǎn)來(lái)討論spring內(nèi)部怎么保證這些執(zhí)行時(shí)機(jī)得以嚴(yán)禁的執(zhí)行候生,還有如何來(lái)擴(kuò)展spring的bean工廠后置處理器);首先通過(guò)一張圖簡(jiǎn)單的理解一下spring容器啟動(dòng)的時(shí)候執(zhí)行調(diào)用BeanFactoryPostProcessor后置處理器的大概的方法執(zhí)行順序:

BeanFactoryPostProcessor的方法執(zhí)行順序

? ? ? ?上圖大概分為④步(這里只是討論spring如何調(diào)用BeanFactoryPostProcessor绽昼,在調(diào)用之前到底執(zhí)行了那些方法唯鸭,上圖并不是spring容器啟動(dòng)的所有步驟)
①啟動(dòng)main方法,在main方法里面調(diào)用
AnnotationConfigApplicationContext的無(wú)參構(gòu)造方法硅确,然后②-1在無(wú)參構(gòu)造方法里面首先實(shí)例化AnnotatedBeanDefinitionReader對(duì)象目溉,實(shí)例化這個(gè)對(duì)象有兩個(gè)非常重要的意義: 1、這個(gè)對(duì)象實(shí)例化出來(lái)有什么用(問(wèn)題一) 菱农; 2缭付、實(shí)例化這個(gè)對(duì)象的過(guò)程中做了哪些事情(問(wèn)題二)

所有的問(wèn)題X啰挪,文章后面再解釋?zhuān)@里先把步驟搞清楚

? ? ? ?繼而②-2spring又實(shí)例化了一個(gè)ClassPathBeanDefinitionScanner對(duì)象滤否,這個(gè)對(duì)象顧名思義就是能夠用來(lái)完成spring的掃描功能,但是這里提一句——spring內(nèi)部完成掃描功能并不是用的這個(gè)對(duì)象瑰步,而是在掃描的時(shí)候又new了一個(gè)新的ClassPathBeanDefinitionScanner對(duì)象;換言之這里spring new的對(duì)象我們假設(shè)他為a绣檬,但是spring在真正完成掃描的時(shí)候又new了一個(gè)b舅巷,但是是同一個(gè)類(lèi)都是ClassPathBeanDefinitionScanner,但是為什么需要兩個(gè)河咽? 3钠右、直接用a不就可以了嗎?如果spring內(nèi)部完成掃描時(shí)候沒(méi)用a忘蟹,那么a被new出來(lái)在哪里使用了飒房?(問(wèn)題三)到此為止第②步完成;③調(diào)用register(Appconfig.class);首先會(huì)把Appconfig類(lèi)解析成為一個(gè)beanDefintion對(duì)象(如何把一個(gè)類(lèi)解析稱(chēng)為beanDefinition對(duì)象的媚值?這里其實(shí)涉及到②-1AnnotatedBeanDefinitionReader對(duì)象的意義狠毯,如果你明白了②-1這里也就明白了),然后給解析出來(lái)的beanDefinition對(duì)象設(shè)置一些默認(rèn)屬性褥芒,繼而put到beanDefintionMap當(dāng)中嚼松;為什么需要put到beanDefintionMap呢?在上一篇我們已經(jīng)解釋過(guò)這個(gè)map就是單純用來(lái)存儲(chǔ)beanDefinition的锰扶,spring后面會(huì)遍歷這個(gè)map根據(jù)map當(dāng)中的beanDefinition來(lái)實(shí)例化bean献酗,如果Appconfig類(lèi)的beanDefintion存在map當(dāng)中那么他必然會(huì)被spring容器實(shí)例化稱(chēng)為一個(gè)bean?為什么Appconfig會(huì)需要實(shí)例化呢坷牛?因?yàn)锳ppconfig當(dāng)中有很多加了@Bean的方法罕偎,這些方法需要被調(diào)用,故而需要實(shí)例化京闰,但是Appconfig類(lèi)的實(shí)例化很復(fù)雜比一般類(lèi)實(shí)例化過(guò)程復(fù)雜很多颜及,涉及到代理涉及到cglib等等,這個(gè)我們后面文章解釋?zhuān)贿@里還需要解釋一個(gè)問(wèn)題蹂楣,為什么Appconfig類(lèi)是通過(guò)register(Appconfig.class);手動(dòng)put到map當(dāng)中呢俏站?為什么不是掃描出來(lái)的呢?(一般類(lèi)都是通過(guò)掃描出來(lái)的)痊土,其實(shí)也很簡(jiǎn)單肄扎,因?yàn)樗麩o(wú)法掃描自己,一般類(lèi)是spring通過(guò)解析Appconfig上的@ComponentScan注解然后被掃描到施戴,所以無(wú)法掃描自己反浓;接下來(lái)便是第④步,④-1到④-4以后分析赞哗,④-5便是我們上篇文章說(shuō)的執(zhí)行spring當(dāng)中的bean工廠后置處理器,也是本文重點(diǎn)討論的辆雾;下圖是對(duì)上述文字的一個(gè)說(shuō)明——spring容器啟動(dòng)的執(zhí)行順序:

spring容器啟動(dòng)的執(zhí)行順序動(dòng)態(tài)圖

接下來(lái)解釋上面文字里的所有問(wèn)題
問(wèn)題一:AnnotatedBeanDefinitionReader這個(gè)對(duì)象實(shí)例化出來(lái)有什么用肪笋?先看一下這個(gè)類(lèi)的javadoc,看看作者怎么來(lái)解釋這個(gè)類(lèi)的
image

Convenient adapter for programmatic registration of annotated bean
classes. * This is an alternative to {@link
ClassPathBeanDefinitionScanner}, applying * the same resolution of
annotations but for explicitly registered classes only

? ? ? ?按照筆者蹩腳的英文水平我的理解是:這個(gè)類(lèi)作用分為以下兩個(gè)
? ? ? ?1、可用于編程式動(dòng)態(tài)注冊(cè)一個(gè)帶注解的bean藤乙,什么意思呢?比如我們有一個(gè)類(lèi)A存在com.shadow包下面猜揪,并且是一個(gè)加注解的類(lèi)。比如加了@Component坛梁,正常情況下這個(gè)類(lèi)A一般是被spring掃描出來(lái)的而姐,但是有不正常情況,比如spring并沒(méi)有掃描到com.shadow包划咐,那么類(lèi)A就無(wú)法被容器實(shí)例化拴念。有人可能會(huì)問(wèn)為什么沒(méi)有掃描到com.shadow包?掃描情況下不會(huì)掃描到褐缠?其實(shí)很簡(jiǎn)單政鼠,假設(shè)你的這個(gè)類(lèi)是動(dòng)態(tài)生成,在容器實(shí)例化的時(shí)候不存在那么肯定不存在队魏,再或者這個(gè)包下面有N多類(lèi)但是只有一個(gè)類(lèi)加了注解公般,那么其實(shí)你不需要去掃描,只需要添加這一個(gè)加了注解的類(lèi)即可胡桨,再或者一個(gè)類(lèi)是你和第三方系統(tǒng)交互后得到的官帘。那么這個(gè)時(shí)候我們可以把這個(gè)類(lèi)通過(guò)AnnotatedBeanDefinitionReaderregister(Class clazz)方法把一個(gè)帶注解的類(lèi)注冊(cè)給spring(這里的注冊(cè)其實(shí)就是上一篇文章中說(shuō)的把一個(gè)類(lèi)解析成BeanDefintion對(duì)象,然后把這個(gè)對(duì)象put到beanDefinitionMap當(dāng)中)昧谊,寫(xiě)個(gè)例子來(lái)測(cè)試一下他的這個(gè)注冊(cè)bean的功能:

手動(dòng)注冊(cè)bean

? ? ? ?2遏佣、可以代替ClassPathBeanDefinitionScanner這個(gè)類(lèi),具備相同的注解解析功能揽浙, ClassPathBeanDefinitionScanner是spring完成掃描的核心類(lèi)状婶,這個(gè)我后面會(huì)分析;簡(jiǎn)而言之馅巷,spring完成掃描主要是依靠ClassPathBeanDefinitionScanner這個(gè)類(lèi)的對(duì)象膛虫,但是AnnotatedBeanDefinitionReader可以替代他完成相同的注解解析,意思就是通過(guò)ClassPathBeanDefinitionScanner掃描出來(lái)的類(lèi)A和通過(guò)AnnotatedBeanDefinitionReader顯示注冊(cè)的類(lèi)A在spring內(nèi)部會(huì)一套相同的解析規(guī)則钓猬;這點(diǎn)上面那個(gè)例子已經(jīng)證明了稍刀。
? ? ? ?那么AnnotatedBeanDefinitionReader除了動(dòng)態(tài)顯示注冊(cè)一些spring掃描不到的類(lèi)之外還有什么功能?在初始化spring容器的過(guò)程中他主要干了什么事情呢敞曹?或者這么說(shuō):假設(shè)程序中沒(méi)有需要?jiǎng)討B(tài)顯示注冊(cè)的類(lèi)他就沒(méi)用了嗎账月?再或者AnnotatedBeanDefinitionReader這個(gè)類(lèi)的對(duì)象除了注冊(cè)一些自己的類(lèi)還有什么應(yīng)用場(chǎng)景呢?——注冊(cè)我們的配置類(lèi)澳迫,對(duì)于不理解是什么配置的讀者可以理解所謂的配置類(lèi)就是那個(gè)加了@Configuration@ComponentScan的那個(gè)類(lèi)局齿,也就是Appconfig.java
? ? ? ?那么問(wèn)題來(lái)了橄登,為什么配置類(lèi)需要手動(dòng)注冊(cè)呢抓歼?很簡(jiǎn)單因?yàn)榕渲妙?lèi)無(wú)法掃描出來(lái)讥此,所以需要我們手動(dòng)注冊(cè)。為什么無(wú)法掃描呢谣妻?比如spring完成掃描是需要解析Appconfig.java當(dāng)中的@ComponentScan注解的值(一般是一個(gè)包名)萄喳,得到這個(gè)值之后去掃描這個(gè)值所代表的包下面的所有bean;簡(jiǎn)單的說(shuō)就是spring如果想要完成掃描必須先提供Appconfig.java蹋半,所以Appconfig.java要在一開(kāi)始就手動(dòng)注冊(cè)給spring他巨,spring得到Appconfig.class之后把他解析成BeanDefintion對(duì)象,繼而去獲取@ComponentScan的值然后才開(kāi)始掃描其他bean减江;
? ? ? ?總結(jié):AnnotatedBeanDefinitionReader的作用:1染突、主要是可以動(dòng)態(tài)、顯示的注冊(cè)一個(gè)bean您市;2觉痛、而且具備解析一個(gè)類(lèi)的功能;和掃描解析一個(gè)類(lèi)的功能相同茵休;AnnotatedBeanDefinitionReader的應(yīng)用場(chǎng)景1薪棒、可以顯示、動(dòng)態(tài)注冊(cè)一個(gè)程序員提供的bean榕莺;2俐芯、在初始化spring容器的過(guò)程中他完成了對(duì)配置類(lèi)的注冊(cè)和解析功能;
? ? ? ?針對(duì)AnnotatedBeanDefinitionReader應(yīng)用場(chǎng)景的第2點(diǎn)钉鸯,我在啰嗦幾句吧史,一般程序員在初始化spring容器的時(shí)候代碼有很多種寫(xiě)法,但都是換湯不換藥的唠雕,我這里舉2個(gè)栗子:
? ? ? ?第一種寫(xiě)法:

AnnotationConfigApplicationContext ac =
                new AnnotationConfigApplicationContext();
                    //動(dòng)態(tài)注冊(cè)一個(gè)配置類(lèi)
        ac.register(Appconfig.class);
                //調(diào)用refresh方法
        //這里很多資料都叫做刷新spring容器
        //但是我覺(jué)得不合適贸营,這是硬核翻譯,比較生硬
        //筆者覺(jué)得理解為初始化spring容器更加精準(zhǔn)
        //至于為什么以后慢慢更新再說(shuō)
        ac.refresh();

? ? ? ?第二種寫(xiě)法:

AnnotationConfigApplicationContext ac =
        new AnnotationConfigApplicationContext(Appconfig.class);

? ? ? ?這兩種寫(xiě)法都初始化spring容器岩睁,代碼上的區(qū)別無(wú)非就是第一種寫(xiě)法是調(diào)用AnnotationConfigApplicationContext()钞脂;的無(wú)參構(gòu)造方法,第二種寫(xiě)法是調(diào)用了AnnotationConfigApplicationContext(Class<?>... annotatedClasses)有參構(gòu)造方法捕儒;但是你如果翻閱源碼第二種寫(xiě)法的內(nèi)部也是首先調(diào)用無(wú)參構(gòu)造方法的冰啃,繼而內(nèi)部繼續(xù)調(diào)用register(Appconfig.class)方法,最后調(diào)用refresh();方法刘莹,和第一種寫(xiě)法的區(qū)別是register和refresh是程序員調(diào)用的阎毅;筆者更推薦第一種寫(xiě)法,因?yàn)榈谝环N寫(xiě)法可以在初始化spring容器之前得到AnnotationConfigApplicationContext的對(duì)象也就是代碼里面的ac對(duì)象点弯;用一張圖來(lái)說(shuō)明一下這兩種寫(xiě)法的異同:

image

? ? ? ?其實(shí)第一種方法和第二種方法都可以得到ac對(duì)象扇调,那么為什么第一種寫(xiě)法筆者推薦呢?首先第二種方法是在spring容器完成初始化之后的到的ac對(duì)象蒲拉,容器已經(jīng)初始化了肃拜,這個(gè)時(shí)候得到這個(gè)對(duì)象能干了事情少了很多痴腌;第一種方法在初始化之前得到的雌团,那么能干的事情可多了燃领。①比如我們可以在容器初始化之前動(dòng)態(tài)注冊(cè)一個(gè)自己的bean,就是上文提到的 AnnotatedBeanDefinitionReader的應(yīng)用場(chǎng)景锦援,②再比如可以利用ac對(duì)象來(lái)關(guān)閉或者開(kāi)啟spring的循環(huán)依賴猛蔽,③還比如程序員可以在容器初始化之前注冊(cè)自己實(shí)例化的BeanDefinition對(duì)象。如果你像筆者一樣精通spring源碼你會(huì)發(fā)覺(jué)提前得到這個(gè)ac對(duì)象可以做的事情太多了灵寺,筆者這里說(shuō)的三個(gè)比如都必須在spring容器初始化之前做才有意義曼库,簡(jiǎn)而言之就是需要在spring調(diào)用refresh方法之間做才有意義。
? ? ? ?如果你不理解我打個(gè)比較污的比方:假設(shè)有機(jī)會(huì)約到某喬姓網(wǎng)紅略板,無(wú)比興奮之后現(xiàn)在來(lái)分析起因和最終結(jié)果毁枯;起因是她愿意出來(lái)和你約會(huì),結(jié)果是約會(huì)完成最終她還是要回家的叮称。但是過(guò)程可以很精彩呀种玛!對(duì)比spring的源碼起因是你首先成功實(shí)例化了一個(gè)ac對(duì)象(ac成功實(shí)例化==你成功約會(huì)==new出來(lái)的ac對(duì)象==約出來(lái)的喬姑娘),結(jié)果是調(diào)用ac.refresh()完成初始化spring容器瓤檐,相當(dāng)于喬姑娘回家==完成約會(huì)赂韵;
? ? ? ?那么你想一下第一種方式是你成功實(shí)例化一個(gè)ac對(duì)象,在完成初始化之前可以肆意妄為挠蛉,除了對(duì)ac這個(gè)對(duì)象為所欲為(調(diào)用ac的api)之外還可以寫(xiě)任何你自己想寫(xiě)的代碼祭示;相當(dāng)于你成功約到喬姑娘,然后****************你可以拿到她的身份證谴古。但是第二種方式相當(dāng)于你約到了喬姑娘质涛,但是約會(huì)的過(guò)程你沒(méi)辦法參與都是姑娘自己安排,她可能和你看完電影之后就告訴你身份證丟了然后各回各家掰担;所以筆者推薦使用第一種方式實(shí)例化spring容器汇陆。。恩敌。瞬测。至于原因我已經(jīng)說(shuō)的夠清楚了。

? ? ? ?我們看下AnnotatedBeanDefinitionReader具體做了什么纠炮,看這個(gè)構(gòu)造方法月趟,傳入的是一個(gè)BeanDefinitionRegistry類(lèi)型,就是可以注冊(cè)bean定義的恢口,內(nèi)部要注冊(cè)就需要用到:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
        this(registry, getOrCreateEnvironment(registry));
    }

? ? ? ?getOrCreateEnvironment獲得或者創(chuàng)建環(huán)境孝宗,如果BeanDefinitionRegistry是EnvironmentCapable的話就可以直接獲取,否則就創(chuàng)建一個(gè)標(biāo)準(zhǔn)環(huán)境耕肩,其實(shí)就是獲取一些系統(tǒng)的變量因妇。比如可以配置dev環(huán)境问潭,test環(huán)境,online環(huán)境等等婚被。

    private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry instanceof EnvironmentCapable) {
            return ((EnvironmentCapable) registry).getEnvironment();
        }
        return new StandardEnvironment();
    }

? ? ? ?繼續(xù)看AnnotatedBeanDefinitionReader另一個(gè)構(gòu)造方法:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

? ? ? ?對(duì)BeanDefinitionRegistry進(jìn)行了保存和把environment封裝進(jìn)了ConditionEvaluator狡忙,ConditionEvaluator可以理解成一個(gè)條件過(guò)濾器,與@Conditional有關(guān)址芯,如果有了這個(gè)注解灾茁,就先判斷條件成不成立,不成立的話有些操作就不做了谷炸。registerAnnotationConfigProcessors這個(gè)一看方法就知道要加一些處理器北专,來(lái)處理我們的注解,也就是說(shuō)旬陡,spring有些內(nèi)部的處理器需要注冊(cè)進(jìn)來(lái)拓颓,這里可以想到spring應(yīng)該是為了統(tǒng)一處理處理器,所以也是按注冊(cè)描孟,處理這樣的流程來(lái)驶睦,無(wú)論是自己內(nèi)部的,還是用戶自定義的画拾,我們來(lái)看看里面是怎么做的啥繁,我們跟進(jìn)這個(gè)方法的源碼:

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        // 獲取beanFactory也就是DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                /**
                 * AnnotationAwareOrderComparator主要能解析@Order和@Priority
                 */
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                /**
                 * ContextAnnotationAutowireCandidateResolver提供處理延遲加載的功能
                 */
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }

        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
        /**
         * spring默認(rèn)的BeanDefinition的注冊(cè),很重要青抛,需要理解每個(gè)bean的類(lèi)型
         */
        // 注冊(cè)ConfigurationAnnotationProcessor
        //ConfigurationClassPostProcessor是一個(gè)工廠后置處理器旗闽,這個(gè)后置處理器非常重要,基本上類(lèi)上面的注解都在這里面判斷并解析蜜另,spring的包掃描也在里面完成
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
        // 注冊(cè)AutowiredAnnotationBeanPostProcessor
        //顧名思義就是處理@Autowired的适室,它是一個(gè)bean的后置處理器,在bean的屬性注入的時(shí)候會(huì)用到
        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
        // 注冊(cè)CommonAnnotationBeanPostProcessor
        //顧名思義就是處理一些公共注解的举瑰,它是一個(gè)bean的后置處理器捣辆,可以處理@PostConstruct和@PreDestroy還有@Resource等
        //提示: 這里有一個(gè)jsr250Present校驗(yàn)
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
        // 注冊(cè)PersistenceAnnotationProcessor
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition();
            try {
                def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                        AnnotationConfigUtils.class.getClassLoader()));
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
            }
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
        // 注冊(cè)EventListenerMethodProcessor
        if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
        }
        // 注冊(cè)DefaultEventListenerFactory
        if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
        }

        return beanDefs;
    }

? ? ? ?主要流程就是獲取DefaultListableBeanFactory,然后注冊(cè)AnnotationAwareOrderComparator順序比較器此迅,排序用的汽畴,ContextAnnotationAutowireCandidateResolver自動(dòng)裝配解析器,解析自動(dòng)裝配相關(guān)配置用耸序。然后創(chuàng)建一些后置處理器的bean定義忍些,內(nèi)部一般用RootBeanDefinition來(lái)定義,比如這個(gè)類(lèi)ConfigurationClassPostProcessor坎怪,他是前面配置類(lèi)處理的關(guān)鍵罢坝,所以這里先添加bean定義,還有AutowiredAnnotationBeanPostProcessor搅窿,處理自動(dòng)裝配的嘁酿,另外還有EventListenerMethodProcessorDefaultEventListenerFactory隙券,CommonAnnotationBeanPostProcessor暫時(shí)不講,后面用到會(huì)說(shuō)闹司。
? ? ? ?我們?cè)賮?lái)看看AnnotatedBeanDefinitionReader的重要屬性:

private final BeanDefinitionRegistry registry;
    //類(lèi)名生成器
    private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
    //socpe注解解析器
    private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
    //條件評(píng)估器
    private ConditionEvaluator conditionEvaluator;

? ? ? ?可以看到娱仔,內(nèi)部的bean定義全部都是用RootBeanDefinition。至此讀取器創(chuàng)建完成开仰,其實(shí)就是注冊(cè)了需要處理注解的處理器bean定義拟枚,此時(shí)還沒(méi)有創(chuàng)建bean哦薪铜。后面ConfigurationClassPostProcessor發(fā)揮著很大的作用众弓,用來(lái)解析配置類(lèi)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末隔箍,一起剝皮案震驚了整個(gè)濱河市谓娃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蜒滩,老刑警劉巖滨达,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異俯艰,居然都是意外死亡捡遍,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)竹握,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)画株,“玉大人,你說(shuō)我怎么就攤上這事啦辐∥酱” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵芹关,是天一觀的道長(zhǎng)续挟。 經(jīng)常有香客問(wèn)我,道長(zhǎng)侥衬,這世上最難降的妖魔是什么诗祸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮轴总,結(jié)果婚禮上直颅,老公的妹妹穿的比我還像新娘。我一直安慰自己肘习,他們只是感情好际乘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著漂佩,像睡著了一般脖含。 火紅的嫁衣襯著肌膚如雪罪塔。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天养葵,我揣著相機(jī)與錄音征堪,去河邊找鬼。 笑死关拒,一個(gè)胖子當(dāng)著我的面吹牛佃蚜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播着绊,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼谐算,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了归露?” 一聲冷哼從身側(cè)響起洲脂,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剧包,沒(méi)想到半個(gè)月后恐锦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疆液,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年一铅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堕油。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡潘飘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出馍迄,到底是詐尸還是另有隱情福也,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布攀圈,位于F島的核電站暴凑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏赘来。R本人自食惡果不足惜现喳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望犬辰。 院中可真熱鬧嗦篱,春花似錦、人聲如沸幌缝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至浴栽,卻和暖如春荒叼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背典鸡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工被廓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人萝玷。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓嫁乘,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親球碉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜓斧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354