当使用@postconstruct执行某个方法时,
其中包含applicationContext.getBean(Class) 会报空指针异常
applicationContext.getBean(clazz)
- public
T getBean(Class requiredType) throws BeansException { - this.assertBeanFactoryActive();
- return this.getBeanFactory().getBean(requiredType);
- }
造成这个问题的原因其实是 applicationContext.getBean(Class) 是从已经被spring实例化的对象中寻找,如果该对象还未实例化,则获取不到。
也就是通过@PostConstruct 注解在HandlerMsgData构造函数执行完成后才执行的initAllHandler() , 此时有些对象还未被spring实例化,所以该方法获取到结果并不完整。
如果是想通过调整bean是实例化对象初始化顺序来解决该问题,则成本比较大(大型工程中依赖关系很复杂)。
所以最好的解决方式就是在获取时检查一次allHandler里是否存在指定数据,如果不存在则再次执行initAllHandler () , 这就相当于同步了一下缓存的数据。
补充一下:
Bean是什么时候被实例化的?
对于Prototype: 在第一次请求的时候才被实例化的
对于Singleton:
一般在IoC容器启动的时候就被实例化,然后被缓存在内存中
如果bean标签中有设置lazy-init=true,则会在第一次请求时才会被实例化,而不是在容器启动的时候就被实例化
但是,当一个懒实例化的Bean依赖了一个非懒实例化的Bean,那么IOC容器在启动的时候也会实例化这个Bean,因为它必须满足单例的依赖性
spring boot 2.2 新增全局懒加载属性,开启后全局 bean 被设置为懒加载,需要时再去创建
spring: main: lazy-initialization: true #默认false 关闭
个别 bean 可以通过设置 「@Lazy(false)」 排除,设置为启动时加载
@Lazy(false) @Configuration public class DemoConfig {}
当然也可以指定规则实现 LazyInitializationExcludeFilter 规则实现排除
@Bean LazyInitializationExcludeFilter integrationLazyInitExcludeFilter() { return LazyInitializationExcludeFilter.forBeanTypes(DemoConfig.class); }
全局懒加载的问题
通过设置全局懒加载,我们可以减少启动时的创建任务从而大幅度的缩减应用的启动时间。但全局懒加载的缺点可以归纳为以下两点:
Bean生命周期源码追踪