当使用@postconstruct执行某个方法时,

其中包含applicationContext.getBean(Class) 会报空指针异常

applicationContext.getBean(clazz)
public <T> T getBean(Class<T> 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,因为它必须满足单例的依赖性

SpringBoot 全局懒加载机制

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); }


全局懒加载的问题

通过设置全局懒加载,我们可以减少启动时的创建任务从而大幅度的缩减应用的启动时间。但全局懒加载的缺点可以归纳为以下两点:

  • Http 请求处理时间变长。 这里准确的来说是第一次 http 请求处理的时间变长,之后的请求不受影响(说到这里自然而然的会联系到 spring cloud 启动后的第一次调用超时的问题)。

spring 用注解排除不存在数据库的字段 spring注解找不到bean_spring boot

Bean生命周期源码追踪