以下顺序为现象-》解决方法-》原因-》复现过程
现象
在被@PostConstrust注解注释的接口中,使用自建SpringUtils,服务无法启动,报告NPE(Null Pointer Exception:空指针异常)。
解决方法
推荐解决方法是改用ApplicationRunner
/CommandLineRunner
的方式来替代@PostConstruct
实现需求,此两者最终实现效果与@PostConstruct
相同,且可使用@AutoWired
注解来直接获取Bean。
原因
在spring服务启动过程中,spring会先去注册所有的bean,在注册过程中,如果发现该bean中包涵了被@PostConstruct
注释的函数,那么就会先去执行这个函数,然后再继续注册其他未注册的bean。但是在springUtils中,无论是继承ApplicationListener,还是继承自ApplicationContextAware,都只有在bean初始化完成后,才会执行注入applicationContext。
复现过程
SpringUtils.java
public class SpringUtils implements ApplicationListener<ApplicationEvent> {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent) {
ContextRefreshedEvent e = (ContextRefreshedEvent)event;
if (e.getApplicationContext().getParent() == null) {
applicationContext = e.getApplicationContext();
}
}
}
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
}
TestService.java(为减少测试代码量,不使用接口模式)
@Service
public class TestService{
}
TestInit.java
@Component
public class TestInit{
@PostConstruct
public void init(){
SpringUtils.getBean(TestService.class);
}
}
结果:
空指针异常