最近遇到個場景,需要在使用@Bean注解定義bean的時候為對象設置一些屬性,比如掃描路徑,因為路徑經常發布新特性的時候需要修改,所以就計划着放在配置文件中,然后通過@ConfigurationProperties或@Value結合@PropertySource注入,類似如下:
@Configuration @PropertySource("classpath:application.properties") public class AbcConfig { @Value("${myconfig}") private String myconfig; }
但是只要在Config類中,myconfig就怎么都無法注入。
改成使用configurationproperties獲取后,仍然無法注入。
@Configuration @ConfigurationProperties(prefix = "mybatis") @PropertySource("classpath:application.properties") public class AbcConfig { private String myconfig; }
和@Value一樣,在非Config注解的普通bean中都能夠正常注入。
於是搜了下網上,有個帖子說在Config配置類中顯示定義PropertySourcesPlaceholderConfigurer即可,如下:
@Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); }
但是我們發現仍然無法注入。於是采用最原始的方法,依賴Environment來獲取,結果發現它也沒有自動注入,一直為null(注,這里可能是因為我們在依賴Environment的Bean上顯示定義了@Order(1)優先創建的原因)。最后只要讓bean實現EnvironmentAware接口顯示設置,如下:
@PropertySource("classpath:myconfig.properties") @Configuration public class AbcConfig implements EnvironmentAware { private Environment env; @Override public void setEnvironment(Environment environment) { this.env=environment; } }
然后使用env.getProperty就可以獲取到配置了。
備注:@configurationproperties和@value區別如下:
@ConfigurationProperties和@Value的選用
如果只是在某個業務邏輯中需要獲取一下配置文件中的某項值,使用@Value;
如果專門編寫了一個javaBean來和配置文件進行映射如datasource,我們就直接使用@ConfigurationProperties;
最后,為啥原理很重要,這個時候就體現在對整體流程以及體系是否熟悉,如果熟悉就知道問題如何解決,否則不知道往哪里去,這也是面試的時候,我們經常會問或者被問及spring boot自動配置原理的原因。