如何把 profile 作为静态变量 任意随时使用 无需 @value(“${spring.profiles.acitve”}
看了很多 获取 变量的例子: 大多是用
@value("${spring.profiles.acitve"}
赋值给对象的属性
不满意止步于此,而且对我来说,根本不能用
该方式缺点:@value("${spring.profiles.acitve"}
- 不能在 静态方法中使用,不能作为static 变量直接注入后使用,无法提炼到静态工具类方法中。
- 不能在 早期使用,必须等待
springcontext
完全加载后,才能使用该对象。原因是 作为对象的属性,必须被容器管理后,才能被调用。当 spring 容器 没有完全启动时,也无法加载该参数。
解决方案: 从Enviroment 获取
- 利用 事件监听器,监听早期
spring
加载Enviroment
环境参数完成的事件ApplicationEnvironmentPreparedEvent
。 - 该事件包含了
profile
等信息,而且加载时机非常早,在一系列SpringApplicationEvent
中 仅次于ApplicationStartingEvent
,见下图。 而ApplicationStartingEvent
因为太过早期,所以不建议使用。
- 该事件基本上把 所有的参数,都加载进了
org.springframework.core.env.ConfigurableEnvironment
.
包含如下这些方式配置的参数,优先级如下 :
当 springcloud 项目时,config server 从bootstrap.yml
中配置,优先于application.yml
- 加载过程源码解析
- 在步骤4中,就会执行到 我们自定义的 监听器了 。而且可以获取到 该
Environment
,进而获取spring 帮我们整理好的全部参数
代码实现:
-
自定义监听器的代码如下
SpringApplicationEventListener
:import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.event.SpringApplicationEvent; import org.springframework.context.ApplicationListener; /** * 监听 ApplicationEnvironmentPreparedEvent 事件,第一时间 获取 profile 信息, 设置为 static 变量备用 ,一并设置 isProd,isDev,isTest 备用 * * 代码参考 https://stackoverflow.com/questions/48837173/unable-to-intercept-applicationenvironmentpreparedevent-in-spring-boot * * @see SpringApplication#prepareEnvironment(org.springframework.boot.SpringApplicationRunListeners, org.springframework.boot.ApplicationArguments) * * @author stormfeng * @date 2022-08-23 16:44 */ @Slf4j public class SpringApplicationEventListener implements ApplicationListener<SpringApplicationEvent> { // 这几个 静态变量,可以很方便的在其他类中作为工具使用 public static String profile; public static boolean isProd,isDev,isTest; /** * 监听 SpringApplicationEvent */ @Override public void onApplicationEvent(SpringApplicationEvent event) { log.debug("监听到 SpringApplicationEvent :{}", event.getClass().getSimpleName()); if (event instanceof ApplicationEnvironmentPreparedEvent) { final ApplicationEnvironmentPreparedEvent e = (ApplicationEnvironmentPreparedEvent) event; final String[] activeProfiles = e.getEnvironment().getActiveProfiles(); profile = activeProfiles[0]. initProfile(); log.info("监听到 SpringApplicationEvent :{},设置profile :{}", event.getClass().getSimpleName(), profile); } } private void initProfile() { isProd = "prod".equalsIgnoreCase(profile); isTest = "test".equalsIgnoreCase(profile); isDev = "dev".equalsIgnoreCase(profile); }
-
此时因springContext尚未完全加载,因此不能使用
@EventListener
自动注入监听器 ,必须手动添加listeners()
@SpringBootApplication public class BootApplication { public static void main(String[] args) { new SpringApplicationBuilder(BootApplication.class).listeners(new SpringApplicationEventListener()).build().run(args); log.info("----------------------Application start complete--------------------------"); } }