最近遇到个场景,需要在使用@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自动配置原理的原因。