为何getEnvironment().getActiveProfiles()返回未生效的激活配置文件?
问题背景
在Spring Framework 6中,获取激活配置文件存在三种方式:
- 通过
ApplicationContext.getEnvironment().getActiveProfiles()获取 - 通过SpEL表达式
#{systemProperties['spring.profiles.active']}注入获取 - 通过Java系统属性
System.getProperty("spring.profiles.active")获取
两种场景下的表现:
- Alpha场景:创建Spring上下文前设置
spring.profiles.active为prod,log,info,三种方式返回结果一致,对应配置的Bean正常创建。 - Beta场景:创建Spring上下文后再设置该系统属性,实际配置文件未生效(对应Bean未创建),但第一种方式仍返回
prod、log、info,第二种方式返回null,第三种方式返回prod,log,info。
问题解答
1. 为何getEnvironment().getActiveProfiles()会返回未生效的激活配置文件?
Spring的Environment在ApplicationContext初始化阶段就完成了激活Profiles的解析逻辑,该结果直接用于判断哪些Bean需要实例化加载。一旦上下文初始化完成,Bean的创建流程已执行完毕,后续修改系统属性不会触发上下文重新刷新,新的Profiles自然无法生效。
而getActiveProfiles()的返回值是基于Environment内部属性源动态解析的:当你在上下文创建后设置spring.profiles.active系统属性,该属性会被加入Environment的系统属性源中。首次调用getActiveProfiles()时,它会重新从属性源读取并解析该值,但这个动作发生在Bean创建之后,因此虽然返回了新的Profiles值,对应的Bean却错过了加载时机,最终表现为“返回值存在但配置未生效”。
2. 为何基于SpEL的方式能正确显示配置文件未生效的状态(返回null)?
SpEL表达式#{systemProperties['spring.profiles.active']}的注入时机是在Bean初始化过程中。Beta场景下,创建Spring上下文时还未设置spring.profiles.active系统属性,因此Bean初始化注入该值时,系统属性中不存在对应键,返回null。
由于Spring单例Bean初始化完成后不会自动重新注入属性,后续修改系统属性也不会更新已注入的值。因此这个null准确反映了上下文初始化时的真实状态——当时无激活Profiles,对应Bean未被创建,也就正确体现了配置未生效的情况。
内容的提问来源于stack exchange,提问作者Manuel Jordan

