Loading... ## 背景 部署海外项目时,需要初始化后执行定时任务,又需要区分环境,通过下述代码执行时国内无异常难以复现,但国外资源比较差出现空指针: <!--more--> ```java @Component public class XxxTask { @Resource private ApplicationContext applicationContext; @PostConstruct public void handle() { // System.getProperty("spring.profiles.active") 同样空指针 String env = applicationContext.getEnvironment().getActiveProfiles()[0]; if ("hw-test".equals(env) || "hw-prod".equals(env)) { return; } ... } } ``` ## 原因 `@PostConstruct`是JavaEE5中引入,作用于Servlet生命周期的注解,实现**Bean初始化之前**的自定义操作。(同期还有 `@PreDestroy`注解作用于销毁之前)  也就是说在注解生效时,通过 `@Resource`注入的ApplicationContext还没有被初始化,所以在获取的时候报了 `NullPointerException`。 ### `@PostConstruct`特点 1. 只有一个非静态方法能使用此注解 2. 被注解的方法不得有任何参数 3. 被注解的方法返回值必须为void 4. 被注解方法不得抛出已检查异常 5. 此方法只会被执行一次 6. 使用此注解时会影响服务启动时间。服务启动时会扫描WEB-INF/classes的所有文件和WEB-INF/lib下的所有jar包。 ## 解决方案 ```java @DependsOn("springUtils") @Component public class XxxTask { @PostConstruct public void handle() { String env = SpringUtils.getActiveProfile(); if ("hw-test".equals(env) || "hw-prod".equals(env)) { return; } ... } } ``` **注意:** 1. SpringUtils只是copy了Hutool工具包中的SpringUtil,直接引入启动时会报找不到方法所在。 2. 定时任务都不推荐使用Hutool的SpringUtil来直接区分环境,实际测试中有几率执行在Bean初始化之前。 Spring的 `@DependsOn`可以在类(@Component)或方法(@Bean)上使用,将所需要的前置依赖Bean提前放到IOC容器中,以此来指定Bean的加载顺序。(PS:Spring相关的注解会默认将首字母转成大写) --- 除此之外服务出现了无限重启的情况,排查发现是运维监控检测地址配错了。 Last modification:August 24, 2022 © Allow specification reprint Like 0 喵ฅฅ