? ? ? ?在上一篇文章里面我們討論了一個(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í)行順序:
? ? ? ?上圖大概分為④步(這里只是討論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í)行順序:
接下來(lái)解釋上面文字里的所有問(wèn)題
問(wèn)題一:
AnnotatedBeanDefinitionReader
這個(gè)對(duì)象實(shí)例化出來(lái)有什么用肪笋?先看一下這個(gè)類(lèi)的javadoc,看看作者怎么來(lái)解釋這個(gè)類(lèi)的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ò)AnnotatedBeanDefinitionReader
的register(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的功能:
? ? ? ?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ě)法的異同:
? ? ? ?其實(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)裝配的嘁酿,另外還有EventListenerMethodProcessor
和DefaultEventListenerFactory
隙券,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)。