16-入坑:实现了SmartInitializingSingleton却不执行

问题现场

SmartInitializingSingleton是spring的扩展点之一,主要用于在Spring容器启动完成时进行扩展操作,即afterSingletonsInstantiated()。接口的bean的作用域必须是单例,afterSingletonsInstantiated()才会触发。
问题代码:代码中实现了spring提供的SmartInitializingSingleton接口,并实现了afterSingletonsInstantiated方法,但是却不执行。
代码如下:

@Configuration
public class TestSmartInitializingSingleton implements SmartInitializingSingleton {

    @Override
    public void afterSingletonsInstantiated() {
        System.out.println("TestSmartInitializingSingleton.afterSingletonsInstantiated ===========>");
    }

}

application.yaml中配置了懒加载

spring:
  main:
    lazy-initialization: true

现象:

  1. 启动项目发现在SpringBoot 2.2.6.RELEASE版本下afterSingletonsInstantiated不执行,升级SpringBoot版本2.6.11之后afterSingletonsInstantiated执行了。
  2. 在低版本中去掉yaml中懒加载配置也能成功执行。

所以高版本该是已经解决了这个问题,但是工作的项目SpringBoot版本一般不轻易升级。所以需要在不升级版本的情况下找到低版本和高版本的区别并找到解决方法。(不想去掉懒加载)

发现问题

先去掉懒加载配置并在低版本afterSingletonsInstantiated方法上打断点,查看调用栈发现调用的地方在
DefaultListableBeanFactory.preInstantiateSingletons
image.png
现在我们打开懒加载并在这个for循环上打上条件断点
image.png
发现运行到这行的时候这个bean是null
image.png
于是看代码发现861行,懒加载的bean不会实例化
image.png
于是现在的问题是这个bean的lazyInit为啥是true
查看代码发现lazyInit字段在LazyInitializationBeanFactoryPostProcessor的postProcessBeanFactory方法中修改成了true
image.png
总算是找到了原因了,那为啥高版本没有问题呢? 通过debug发现高版本中多了个LazyInitializationExcludeFilter过滤器。
image.png
这个过滤器作用是判断bean是否为SmartInitializingSingleton实现,如果是则排除,也即不会设置lazyInit为true。

解决方案

发现了问题之后,解决就简单了,只要在低版本下实现一个LazyInitializationExcludeFilter过滤器排除SmartInitializingSingleton就好。
image.png
哈哈,果然afterSingletonsInstantiated执行了
image.png

再问

为啥这个方法是否执行和全局懒加载相关?

image.png
当这个配置是true的时候,会添加LazyInitializationBeanFactoryPostProcessor
image.png

  • 29
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

层巅余落日

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值