Spring Boot中@ConditionalOnProperty无法读取自定义配置文件属性
这个问题我之前也碰到过,核心原因其实是**@ConditionalOnProperty的生效时机比@PropertySource更早**——Spring在判断是否要创建MyConfiguration这个Bean的时候,你的myproperties.properties还没通过@PropertySource加载进来,自然读不到属性值;而application.properties是Spring Boot默认优先加载的核心配置,所以条件注解能正常识别。
下面给你两个实用的解决办法,按需选择:
方法一:用Spring Boot的spring.config.import导入配置(推荐)
这是最符合Spring Boot配置规范的方式,不需要修改任何Java代码,只需要在你的application.properties里加一行配置:
spring.config.import=classpath:myproperties.properties
加完之后,你可以把@SpringBootApplication和MyProperties上的@PropertySource注解都删掉——Spring Boot会自动把这个自定义配置文件当成核心配置的一部分加载,@ConditionalOnProperty(name = "mycustomprop.myproperty")就能正常读取属性值了。
方法二:自定义EnvironmentPostProcessor提前加载配置
如果不想修改application.properties,可以通过扩展Spring Boot的环境处理器,在上下文初始化之前就把自定义配置文件加载进来:
- 创建一个实现
EnvironmentPostProcessor的类:
import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.PropertiesPropertySource; import org.springframework.core.io.ClassPathResource; import java.io.IOException; import java.util.Properties; public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor { @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { try { // 加载自定义配置文件 ClassPathResource resource = new ClassPathResource("myproperties.properties"); Properties properties = new Properties(); properties.load(resource.getInputStream()); // 把配置放到环境变量的最前面,确保优先级 environment.getPropertySources().addFirst(new PropertiesPropertySource("myproperties", properties)); } catch (IOException e) { throw new RuntimeException("Failed to load custom properties file", e); } } }
- 在
src/main/resources/META-INF/spring.factories里注册这个处理器:
org.springframework.boot.env.EnvironmentPostProcessor=com.yourpackage.CustomEnvironmentPostProcessor
(记得把com.yourpackage换成你实际的包名)
这样自定义配置文件会在Spring处理@ConditionalOnProperty之前就被加载到环境中,条件注解就能正常识别属性了。
补充说明
为什么原来的@PropertySource不行?因为@PropertySource是和@Configuration绑定的,只有当Spring解析到这个配置类的时候才会加载配置文件;而@ConditionalOnProperty是在Spring决定是否要创建这个配置类的Bean之前就执行的判断逻辑,这时候自定义配置还没被加载,所以读不到值。
内容的提问来源于stack exchange,提问作者Bilgehan

