




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第SpringBoot自動(dòng)配置失效的解決方法目錄問題描述@EnableConfigurationProperties注解行為配置有效,AutoTestConfiguration未刷新
prefix-type@ConditionalOnProperty@ConditionalOnPropertymatch邏輯@ConditionalOnPropertyskip邏輯
總結(jié)本文源自近期項(xiàng)目中遇到的問題,bug總是出現(xiàn)在你自以為是的地方...
問題描述
下面是一個(gè)簡(jiǎn)單復(fù)現(xiàn)的代碼片段,在你沒有閱讀完本文時(shí),如果能做出正確的判斷,那恭喜你可以節(jié)省閱讀本文的時(shí)間了。
1、自動(dòng)配置類:AutoTestConfiguration
@Configuration
@EnableConfigurationProperties(TestProperties.class)
@ConditionalOnProperty(prefix="test",name="enable")
publicclassAutoTestConfiguration{
@Bean
@ConditionalOnMissingBean
publicTestBeantestBean(TestPropertiesproperties){
System.out.println("thisisexecuted.....");
returnnewTestBean();
}
2、配置類TestProperties
@ConfigurationProperties(prefix="test")
publicclassTestProperties{
privatebooleanenable=true;
publicbooleanisEnable(){
returnenable;
publicvoidsetEnable(booleanenable){
this.enable=enable;
這兩個(gè)類都在rootpackage下,可以保證能夠正常被Spring掃描到;那么問題是TestBean會(huì)不會(huì)被正常創(chuàng)建?當(dāng)然這里的結(jié)論是不會(huì)。
可能有的同學(xué)會(huì)說你的TestProperties沒有加@Configuration注解,Spring不認(rèn)識(shí)它,那真的是這樣嗎?很顯然也不是。
在排查這個(gè)問題的過程中,也有遇到其他問題,也是之前沒有遇到過的;即使Spring源碼我看過很多遍,但是仍然會(huì)有一些邊邊角角讓你意想不到的地方;下面就針對(duì)這個(gè)問題,慢慢來揭開它的面紗。
@EnableConfigurationProperties注解行為
在之前的版本中,TestProperties是有被@Configuration注解標(biāo)注的
@Configuration//可以被spring掃描
@ConfigurationProperties(prefix="test")
publicclassTestProperties{
privatebooleanenable=true;
publicbooleanisEnable(){
returnenable;
publicvoidsetEnable(booleanenable){
this.enable=enable;
常規(guī)的思路是,當(dāng)TestProperties被掃描到之后,springenv中就會(huì)有test.enable=true的k-v存在,當(dāng)執(zhí)行AutoTestConfiguration自動(dòng)配置類刷新時(shí),@ConditionalOnProperty(prefix="test",name="enable")則會(huì)生效,進(jìn)而TestBean被正常創(chuàng)建。
但事實(shí)并非如此,下面是對(duì)于此問題的驗(yàn)證
配置有效,AutoTestConfiguration未刷新
兩個(gè)點(diǎn):
AutoTestConfiguration#testBean執(zhí)行會(huì)輸出一個(gè)log(用于判斷AutoTestConfiguration是否正常刷新)
監(jiān)聽ApplicationReadyEvent事件,拿test.enable值(用于判端配置是否正常加載,也就是TestProperties是否被正常刷新)
代碼如下:
@SpringBootApplication
publicclassApplicationimplementsApplicationListenerApplicationReadyEvent{
@Autowired
privateApplicationContextapplicationContext;
publicstaticvoidmain(String[]args){
SpringApplication.run(Application.class,args);
@Override
publicvoidonApplicationEvent(ApplicationReadyEventevent){
System.out.println(this.applicationContext.getEnvironment().getProperty("test.enable")+"------");
執(zhí)行得到的結(jié)果是AutoTestConfiguration#testBean沒有被執(zhí)行,但test.enable為true。
這里說明TestProperties是有被刷新的,但是并沒有對(duì)@ConditionalOnProperty起到作用,那么這里基本可以猜到是自動(dòng)配置類上的@ConditionalOnProperty和@EnableConfigurationProperties的作用順序問題。
在驗(yàn)證順序問題之前,我嘗試在perties中增加如下配置,rerun項(xiàng)目:
test.enable=true
到這里我得到了另一個(gè)bean沖突的問題。
prefix-type
異常提示如下:
Parameter0ofmethodtestBeanincom.glmapper.bridge.boot.config.AutoTestConfigurationrequiredasinglebean,but2werefound:
-testProperties:definedinfile[/Users/glmapper/Documents/project/exception-guides/target/classes/com/glmapper/bridge/boot/config/TestProperties.class]
-test-com.glmapper.bridge.boot.config.TestProperties:definedinnull
這里出現(xiàn)了test-com.glmapper.bridge.boot.config.TestProperties這個(gè)name的bean。我嘗試在代碼中去檢查是否有顯示給定這個(gè)bean名字,但是沒有找到,那只有一種可能,就是這個(gè)是被spring自己創(chuàng)建的。
這個(gè)過程在spring刷新階段非??壳埃谂挪檫@個(gè)問題時(shí),還是耽誤了一些時(shí)間,最后還是把問題定位一致前置到beandefinitions初始化才找到。
這里是@EnableConfigurationProperties注解的一個(gè)行為,依賴EnableConfigurationPropertiesRegistrar,源碼如下:
classEnableConfigurationPropertiesRegistrarimplementsImportBeanDefinitionRegistrar{
.getQualifiedAttributeName(EnableConfigurationPropertiesRegistrar.class,"methodValidationExcludeFilter");
@Override
publicvoidregisterBeanDefinitions(AnnotationMetadatametadata,BeanDefinitionRegistryregistry){
registerInfrastructureBeans(registry);
registerMethodValidationExcludeFilter(registry);
ConfigurationPropertiesBeanRegistrarbeanRegistrar=newConfigurationPropertiesBeanRegistrar(registry);
//toregister
getTypes(metadata).forEach(beanRegistrar::register);
通過代碼比較容易看出,EnableConfigurationPropertiesRegistrar會(huì)將目標(biāo)metadata注冊(cè)成bean;繼續(xù)debug,找到了產(chǎn)生prefix-type格式name的bean。
下面是getName的具體代碼
privateStringgetName(Classtype,MergedAnnotationConfigurationPropertiesannotation){
//拿prefix
Stringprefix=annotation.isPresent()annotation.getString("prefix"):"";
//prefix+"-"+類全限定名
return(StringUtils.hasText(prefix)prefix+"-"+type.getName():type.getName());
到這里我們先明確一個(gè)問題:
如果你使用@EnableConfigurationProperties來開啟配置類,那么就不要在配置類上使用@Configuration等能夠被Springscan識(shí)別到的注解,以免在后續(xù)的使用中同一類型的bean多個(gè)實(shí)例
@ConditionalOnProperty
在回到配置不生效問題上來,這里在官方issue是有記錄的:/spring-proj…
不過這里還是通過分析代碼來還原下問題產(chǎn)生的根本原因;這里主要從兩個(gè)方面來分析:
@ConditionalOnPropertymatch值邏輯,需要明確在匹配value時(shí),從哪些PropertySource讀取的。
@ConditionalOnPropertymatch失敗和bean刷新的邏輯
@ConditionalOnPropertymatch邏輯
首先是@ConditionalOnProperty在執(zhí)行計(jì)算時(shí),匹配value的值來源問題,通過debug代碼很容易就得到了所有的source來源,如下圖:
從debug看,本案例有4個(gè)來源(具體如上圖),實(shí)際上從源碼來看,source涵蓋了springenv所有來源:
[ConfigurationPropertySourcesPropertySource{name='configurationProperties'},
StubPropertySource{name='servletConfigInitParams'},
StubPropertySource{name='servletContextInitParams'},
PropertiesPropertySource{name='systemProperties'},OriginAwareSystemEnvironmentPropertySource{name='systemEnvironment'},
RandomValuePropertySource{name='random'},
OriginTrackedMapPropertySource{name='Configresource'classpathresource[perties]'vialocation'optional:classpath:/''}]
所以本文案例中不生效原因就是上面這些PropertySource都沒有test.enable,也就是TestProperties沒被刷新,或者其在自動(dòng)配置類之后才刷新。
@ConditionalOnPropertyskip邏輯
這里主要解釋@ConditionalOnPropert和bean被刷新的邏輯關(guān)系,具體實(shí)現(xiàn)在ConditionEvaluator類中
publicbooleanshouldSkip(@NullableAnnotatedTypeMetadatametadata,@NullableConfigur
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 軟件設(shè)計(jì)師考試全面分析試題及答案
- 網(wǎng)絡(luò)互聯(lián)技術(shù)及其應(yīng)用試題及答案
- 政治參與中的意愿與行為研究試題及答案
- 西方政治制度與國(guó)際法的重要性及影響分析試題及答案
- 團(tuán)隊(duì)文化在項(xiàng)目管理中的作用試題及答案
- 政治算法在民主決策中的應(yīng)用試題及答案
- 壹釋機(jī)電工程考試內(nèi)容知識(shí)的核心要素試題及答案
- 公共政策解析與評(píng)估試題及答案
- 新時(shí)代背景下公共政策的創(chuàng)新研究試題及答案
- 透視2025年西方政治制度的社會(huì)結(jié)構(gòu)試題及答案
- 婦產(chǎn)科學(xué)知到智慧樹章節(jié)測(cè)試課后答案2024年秋溫州醫(yī)科大學(xué)
- 四年級(jí)下冊(cè)勞動(dòng)《小小快遞站》課件
- 2024年危險(xiǎn)化學(xué)品倉(cāng)庫(kù)安全檢查表
- 工廠實(shí)驗(yàn)室規(guī)章制度(二篇)
- 小腸破裂表現(xiàn)與治療
- 國(guó)開(福建)2024年《Android智能手機(jī)編程》形考任務(wù)1-3答案
- 高校新教師科研能力培養(yǎng)方案
- 世說新語30則名篇原文
- 氣壓傳動(dòng)課件 項(xiàng)目一任務(wù)一 氣動(dòng)剪切機(jī)氣源裝置認(rèn)識(shí)與調(diào)試
- 2023年科學(xué)養(yǎng)羊技術(shù)大全
- 2024秋期國(guó)家開放大學(xué)本科《中國(guó)法律史》一平臺(tái)在線形考(第一至三次平時(shí)作業(yè))試題及答案
評(píng)論
0/150
提交評(píng)論