亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

在SpringBoot1.5.X時

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

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

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

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

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

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

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

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

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

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

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

就可能導(dǎo)致無效問題

例如如下代碼:

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

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

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

注意點

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

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

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

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

解決有兩種方式:

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

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

總結(jié)

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

相關(guān)文章

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

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

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

    SpringMVC中的SimpleUrlHandlerMapping用法詳解

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

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

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

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

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

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

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

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

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

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

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

    java后端解決跨域的幾種問題解決

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

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

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

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

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

最新評論