Spring Boot已激活多Profile却无法解析spring.profiles.active[0]占位符
为何Spring无法注入已激活的Profile?
我有一个通过命令行指定多个激活Profile启动的Spring Boot控制台应用,简化代码如下:
package tmp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import javax.sql.DataSource; @SpringBootApplication(scanBasePackages = {"tmp"}) @Configuration public class SampleTool implements CommandLineRunner { @Autowired private Environment environment; @Value("${spring.profiles.active[0]}") private String firstProfile; // 为启动JPA添加的虚拟数据源 @Bean public DataSource getDataSource() throws ClassNotFoundException{ DataSourceBuilder dsBuilder = DataSourceBuilder.create(); dsBuilder.driverClassName("com.mysql.jdbc.Driver"); dsBuilder.url("jdbc:mysql://localhost/test"); dsBuilder.username("..."); dsBuilder.password("..."); return dsBuilder.build(); } public void run(String...args) { System.exit(0); } public static void main(String[] args) { SpringApplication.run(SampleTool.class, args); } }
运行时日志显示已激活两个Profile:
2023-02-23 08:34:44.696 INFO 38840 --- [ main] tmp.SampleTool : The following 2 profiles are active: "local-db", "local-wiki"
但应用崩溃并抛出错误:
Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.profiles.active[0]' in value "${spring.profiles.active[0]}"
明明Profile已激活,为何Spring无法注入激活的Profile?
问题原因
spring.profiles.active并非可通过@Value直接读取的标准属性,它是Spring内部用于标识激活Profile的特殊参数,不会被加入到Spring的环境属性源中供@Value解析。日志能打印激活的Profile,是因为Spring启动过程中会主动收集并输出这些信息,但这并不代表它会以普通属性的形式暴露。
即便尝试${spring.profiles.active}也无法获取到值,因为该属性不存在于环境属性集合内。
解决方案
直接使用已注入的Environment对象即可获取激活的Profile:
@Autowired private Environment environment; @Override public void run(String... args) throws Exception { String[] activeProfiles = environment.getActiveProfiles(); if (activeProfiles.length > 0) { String firstProfile = activeProfiles[0]; // 执行后续业务逻辑 } System.exit(0); }
这种方式能可靠获取所有已激活的Profile,包括第一个Profile。如果非要用@Value,可以自定义属性或在启动时将激活的Profile作为自定义参数传入,但这种方式远不如直接使用Environment简洁可靠。
内容的提问来源于stack exchange,提问作者Alexander
相关产品推荐
相关产品推荐

