@Lazy标签解决问题的原理

@Lazy原理解析


最近在重构一个国重项目的时候,用@lazy解决了循环依赖的问题,(在自己的类中又依赖了自己),现在来感性分析(大概理解,不涉及底层代码)一下为什么它能起作用。

1铺垫知识点

  • 循环依赖

是指两个或多个Bean互相依赖的情况,在Spring容器初始化时会出现循环依赖的问题。对于循环依赖,Spring在初始化过程中采用了“提前暴露”的策略,将尚未完全初始化的Bean对象暴露给其他需要依赖的Bean对象,以便后者能够完成初始化。

  • bean对象创建过程

在Spring Boot中,Bean的创建通常是通过Spring容器来完成的。在Spring容器中,Bean的创建包括以下两个阶段:

  1. 实例化(Instantiation):在实例化阶段,Spring容器根据Bean的定义信息(通常是XML配置文件或Java注解)创建Bean的实例。这一阶段通常会调用Bean的无参构造函数来创建对象实例。
  2. 初始化(Initialization):在初始化阶段,Spring容器会将Bean的属性值注入到对象中。属性值通常是通过set方法进行注入的。此外,Bean还可以实现InitializingBean接口或使用@PostConstruct注解来完成初始化操作。

2@lazy解决问题原理

在Spring Boot中,可以通过使用@Lazy注解来解决循环依赖的问题。

当使用@Lazy注解时,Spring Boot会将Bean对象的初始化推迟到第一次使用时才进行。这样,当两个或多个Bean对象存在循环依赖时,其中一个Bean对象在初始化时可以直接引用另一个Bean对象的代理对象(未初始化的对象),而不需要等待另一个Bean对象完全初始化后再进行引用。

具体来说,在循环依赖过程中,当BeanA需要引用BeanB时,如果BeanB还未初始化完成,Spring会创建一个代理对象,代替BeanB提供服务,并将代理对象暴露给BeanA。当BeanB初始化完成后,代理对象会被替换成真正的BeanB对象。

需要注意的是,@Lazy注解只能解决单例模式下的循环依赖问题。如果存在原型模式下的循环依赖,则需要使用其他的解决方案。

3@lazy为什么不能用在原型模式中

  • 单例模式

    单例模式是一种只允许创建一个对象实例的设计模式。在单例模式中,类的构造函数被私有化,外部无法直接通过new关键字创建对象,而是提供一个静态的公共方法getInstance(),用于返回单例对象。通过单例模式可以保证在应用中全局只有一个对象实例,这有助于节约系统资源,并方便在整个应用程序中共享对象

  • 原型模式

    原型模式是一种通过复制现有对象来创建新对象的设计模式。在原型模式中,首先需要定义一个原型对象,然后通过复制这个原型对象来创建新的对象实例。复制可以通过Java中的克隆方法实现。原型模式的优点是在创建新对象时,避免了重复的初始化过程,提高了对象创建的效率。

    原型模式下产生的bean都是已经初始化完全的,所以@lazy不生效

4其他解决循环依赖的办法

  • 三级缓存结解决循环依赖:

    • 三级缓存机制包括:

      • singletonObjects:单例对象缓存,存放完全初始化好的单例对象。
      • earlySingletonObjects:早期单例对象缓存,存放实例化但未初始化的单例对象。
      • singletonFactories:单例对象工厂缓存,存放用于创建单例对象的ObjectFactory。
    • 单例bean初始化完成要经历三部分

      • 实例化(构造函数执行)

      • 属性赋值(字段注入,setter注入)

      • 初始化(@postconstruct注入)

    • 具体过程:

      1. 创建A实例,实例化的时候把A对象工厂放入三级缓存,表示A开始实例化了, 虽然我这个对象还不完整,但是先曝光出来让大家知道

      2. A注入属性时,发现依赖B,此时B还没有被创建出来,所以去实例化B

      3. 同样,B注入属性时发现依赖A,它就会从缓存里找A对象。依次从一级到三级 缓存查询A,从三级缓存通过对象工厂拿到A,发现A虽然不太完善,但是存 在,把A放入二级缓存,同时删除三级缓存中的A,此时,B已经实例化并且初 始化完成,把B放入一级缓存。

      4. 接着A继续属性赋值,顺利从一级缓存拿到实例化且初始化完成的B对象,A对 象创建也完成,删除二级缓存中的A,同时把A放入一级缓存

      5. 最后,一级缓存中保存着实例化、初始化都完成的A、B对象

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值