欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot中@ConditionalOnBean實(shí)現(xiàn)原理解讀

 更新時(shí)間:2023年02月17日 09:23:03   作者:brucelwl  
這篇文章主要介紹了SpringBoot中@ConditionalOnBean實(shí)現(xiàn)原理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

SpringBoot @ConditionalOnBean實(shí)現(xiàn)原理

在SpringBoot1.5.X時(shí)

判斷條件是OR,SpringBoot2.x變?yōu)榱薃ND

在spring 啟動(dòng)過(guò)程中,會(huì)調(diào)用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry后置處理器 調(diào)用ComponentScanAnnotationParser的parse(..)方法解析配置類,實(shí)現(xiàn)類路徑下的類文件掃描,

遍歷被掃描到的類,并通過(guò)@ComponentScan注解上指定的規(guī)則進(jìn)行匹配,默認(rèn)情況下,SpringBoot掃描@Component標(biāo)記的類,( 但是在spring.factories中通過(guò)key org.springframework.boot.autoconfigure.EnableAutoConfiguration指定配置不會(huì)被掃描. 這些配置類會(huì)由@EnableAutoConfiguration導(dǎo)入的AutoConfigurationImportSelector來(lái)處理);

如果出現(xiàn)匹配的類還會(huì)通過(guò)ConditionEvaluator.shouldSkip(...)來(lái)判斷是否忽略這個(gè)類,這時(shí)候會(huì)過(guò)濾掉小部分無(wú)效類,但是不會(huì)在這個(gè)期間應(yīng)用@ConditionalOnBean去驗(yàn)證,

因?yàn)槠潋?yàn)證實(shí)現(xiàn)類OnBeanCondition實(shí)現(xiàn)了接口ConfigurationCondition的getConfigurationPhase()方法,該方法返回值是一個(gè)枚舉值,用于判斷什么時(shí)期應(yīng)用這個(gè)條件驗(yàn)證, shouldSkip()方法會(huì)判斷這個(gè)接口返回值,OnBeanCondition實(shí)現(xiàn)的getConfigurationPhase()返回的是ConfigurationPhase.REGISTER_BEAN,而類掃描期間只會(huì)執(zhí)行沒(méi)有實(shí)現(xiàn)ConfigurationCondition接口,或返回值為null,或?yàn)镃onfigurationPhase.PARSE_CONFIGURATION的驗(yàn)證器.

所以這個(gè)期間不會(huì)應(yīng)用@ConditionalOnBean去驗(yàn)證. 這也可以理解因?yàn)檫@個(gè)時(shí)候有很多類沒(méi)有被遍歷到,現(xiàn)在執(zhí)行OnBeanCondition驗(yàn)證肯定多數(shù)是false.

這也導(dǎo)致很多最終不會(huì)被實(shí)例化為Spring bean的類被包裝成BeanDefinition(實(shí)現(xiàn)類ScannedGenericBeanDefinition ),并注冊(cè)在DefaultListableBeanFactory 的成員beanDefinitionMap中,key為Bean的名稱,同時(shí)Bean的名稱會(huì)保存在List集合beanDefinitionNames中, 對(duì)于一些手動(dòng)注冊(cè)的Bean的名稱會(huì)保存在List集合manualSingletonNames中,

然后對(duì)于parse(..)返回的BeanDefinition集合會(huì)遍歷調(diào)用ConfigurationClassParser的parse(...)遞歸調(diào)用, 當(dāng)解析到配置中有@Bean定義的Bean,并有條件注解時(shí),會(huì)調(diào)用ConditionEvaluator.shouldSkip(...)方法,最終調(diào)用到的是 Condition實(shí)現(xiàn)類的matches(...)方法.

而@ConditionalOnBean注解中的驗(yàn)證實(shí)現(xiàn)類OnBeanCondition,最終判斷是否有指定的bean就是通過(guò)DefaultListableBeanFactory 中的beanDefinitionMap和manualSingletonNames是否包含指定的Bean的名稱來(lái)驗(yàn)證的.

當(dāng)然對(duì)于掃描到的無(wú)效類,在ConfigurationClassPostProcessor的processConfigBeanDefinitions(...)調(diào)用parse()方法后會(huì)調(diào)用this.reader.loadBeanDefinitions(configClasses),來(lái)判斷最終有效的BeanDefinition,這時(shí)候就會(huì)執(zhí)行OnBeanCondition, 移除beanDefinitionMap中無(wú)效的BeanDefinition. 

鑒于類路徑掃描規(guī)則和OnBeanCondition驗(yàn)證實(shí)現(xiàn)原理

就可能導(dǎo)致無(wú)效問(wèn)題

例如如下代碼:

C希望不存在A Bean時(shí)創(chuàng)建,B希望在C bean存在時(shí)創(chuàng)建,示例中A配置了Bean,這時(shí)B C都不應(yīng)該創(chuàng)建,但執(zhí)行結(jié)果是C確實(shí)沒(méi)有創(chuàng)建,而B(niǎo)卻被創(chuàng)建了.

原因就在于類掃描時(shí),C被掃描了,導(dǎo)致beanDefinitionMap存在C 的BeanDefinition.

但是C在this.reader.loadBeanDefinitions(configClasses),中由于條件驗(yàn)證不通過(guò)沒(méi)有創(chuàng)建被移除.(當(dāng)然和類掃描順序也有關(guān)系,如果B能夠在C之后被掃描到,就會(huì)執(zhí)行正常,所以Spring官網(wǎng)建議通過(guò)spring.factories來(lái)配置,指定執(zhí)行順序或者在能夠確定執(zhí)行順序的情況下使用@ConditionalOnBean,但是一定不能通過(guò)文件名來(lái)控制順序)

注意點(diǎn)

如果將示例中的類配置到spring.factories中即時(shí)不指定順序,也能正常執(zhí)行,不會(huì)創(chuàng)建B C,這是由于spring.factories配置文件中的類并不是全部包裝成BeanDefinition然后判斷是否有效的,而是排序后封裝成ConfigurationClass通過(guò)遍歷的方式,同樣是在this.reader.loadBeanDefinitions(configClasses)方法中判斷該類是否通過(guò)條件驗(yàn)證是否有效.

當(dāng)執(zhí)行到B是,C還沒(méi)有被處理,所以導(dǎo)致B也不會(huì)被創(chuàng)建,(這有點(diǎn)屬于巧合導(dǎo)致的正確結(jié)果,所以為了安全還是要執(zhí)行順序,讓B在C之后被處理)

第二種情況, 在配置類中定義Bean,如果使用@ConditionalOnBean依賴的也是配置類中Bean,則執(zhí)行結(jié)果不可控,和配置類加載順序有關(guān)。

示例代碼如下:代碼中是希望Bean3被創(chuàng)建,但是實(shí)際上并沒(méi)有!!!

解決有兩種方式:

1 可以考慮使用@DependsOn來(lái)解決,參看Spring中@DependsOn注解的作用及實(shí)現(xiàn)原理。

2 如果一定要區(qū)分兩個(gè)配置類的先后順序,可以將這兩個(gè)類交與EnableAutoConfiguration管理和觸發(fā)。 也就是定義在META-INF\spring.factories中聲明是配置類, 然后通過(guò)@AutoConfigureBefore、AutoConfigureAfter、AutoConfigureOrder控制先后順序。 因?yàn)檫@三個(gè)注解只對(duì)自動(dòng)配置類生效。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java中常用解析工具jackson及fastjson的使用

    Java中常用解析工具jackson及fastjson的使用

    今天給大家?guī)?lái)的是關(guān)于Java解析工具的相關(guān)知識(shí),文章圍繞著jackson及fastjson的使用展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • SpringMVC中的SimpleUrlHandlerMapping用法詳解

    SpringMVC中的SimpleUrlHandlerMapping用法詳解

    這篇文章主要介紹了SpringMVC中的SimpleUrlHandlerMapping用法詳解,SimpleUrlHandlerMapping是Spring MVC中適用性最強(qiáng)的Handler Mapping類,允許明確指定URL模式和Handler的映射關(guān)系,有兩種方式聲明SimpleUrlHandlerMapping,需要的朋友可以參考下
    2023-10-10
  • SpringBoot中獲取微信用戶信息的方法

    SpringBoot中獲取微信用戶信息的方法

    這篇文章主要介紹了SpringBoot中獲取微信用戶信息的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • nacos服務(wù)注冊(cè)服務(wù)發(fā)現(xiàn)依賴配置詳解

    nacos服務(wù)注冊(cè)服務(wù)發(fā)現(xiàn)依賴配置詳解

    這篇文章主要為大家介紹了nacos服務(wù)注冊(cè)服務(wù)發(fā)現(xiàn)依賴配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Java執(zhí)行cmd命令兩種實(shí)現(xiàn)方法解析

    Java執(zhí)行cmd命令兩種實(shí)現(xiàn)方法解析

    這篇文章主要介紹了Java執(zhí)行cmd命令兩種實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • JavaGUI實(shí)現(xiàn)隨機(jī)單詞答題游戲

    JavaGUI實(shí)現(xiàn)隨機(jī)單詞答題游戲

    這篇文章主要為大家詳細(xì)介紹了JavaGUI實(shí)現(xiàn)隨機(jī)單詞答題游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • Java數(shù)據(jù)結(jié)構(gòu)之循環(huán)隊(duì)列簡(jiǎn)單定義與用法示例

    Java數(shù)據(jù)結(jié)構(gòu)之循環(huán)隊(duì)列簡(jiǎn)單定義與用法示例

    這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)之循環(huán)隊(duì)列簡(jiǎn)單定義與用法,簡(jiǎn)要描述了循環(huán)隊(duì)列的概念、原理,并結(jié)合實(shí)例形式分析了java循環(huán)隊(duì)列的定義與使用方法,需要的朋友可以參考下
    2017-10-10
  • java后端解決跨域的幾種問(wèn)題解決

    java后端解決跨域的幾種問(wèn)題解決

    這篇文章主要介紹了java后端解決跨域的幾種問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • java獲取服務(wù)器基本信息的方法

    java獲取服務(wù)器基本信息的方法

    這篇文章主要介紹了java獲取服務(wù)器基本信息的方法,涉及java獲取系統(tǒng)CPU、內(nèi)存及操作系統(tǒng)等相關(guān)信息的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • 淺談拋出異常和捕獲異常的一些區(qū)別

    淺談拋出異常和捕獲異常的一些區(qū)別

    這篇文章主要介紹了拋出異常和捕獲異常的一些區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06

最新評(píng)論