当前位置: 首页 > wzjs >正文

网站建设需要的东西建邺html5响应式网站

网站建设需要的东西,建邺html5响应式网站,建设社区服务网站的论文,爬虫代理ip购买A 需要 B,而 B 又需要 A,形成一个循环依赖。 1. Spring 如何解决循环依赖? Spring 通过三级缓存机制解决了循环依赖问题,具体步骤如下: 实例化阶段: 当容器创建一个 Bean 时,首先会调用其无参…

A 需要 B,而 B 又需要 A,形成一个循环依赖。

1. Spring 如何解决循环依赖?

Spring 通过三级缓存机制解决了循环依赖问题,具体步骤如下:

  1. 实例化阶段

    • 当容器创建一个 Bean 时,首先会调用其无参构造函数完成实例化(即分配内存,但未进行属性注入)。
    • 实例化完成后,将该 Bean 的“早期引用”(尚未完全初始化的对象)放入三级缓存中。
  2. 属性注入阶段

    • 在为当前 Bean 注入属性时,如果发现依赖的 Bean 尚未完全初始化,则从三级缓存中获取其“早期引用”,完成属性注入。
  3. 初始化阶段

    • 属性注入完成后,执行 Bean 的初始化方法(如 @PostConstruct 或 InitializingBean.afterPropertiesSet())。
    • 初始化完成后,将该 Bean 从三级缓存移动到一级缓存,并清除二级和三级缓存。

三级缓存的具体作用

  1. 一级缓存(singletonObjects

    • 存储完全初始化后的 Bean 实例。
    • 当一个 Bean 完成所有属性注入和初始化后,它会被放入一级缓存中,供后续依赖使用。
  2. 二级缓存(earlySingletonObjects

    • 存储“早期引用”(尚未完全初始化的 Bean 实例)。
    • 如果某个 Bean 在初始化过程中被其他 Bean 依赖,则会从二级缓存中获取其“早期引用”,完成属性注入。
  3. 三级缓存(singletonFactories

    • 存储 Bean 的工厂对象(ObjectFactory),用于动态生成代理对象或其他扩展功能。
    • 三级缓存的主要作用是支持 AOP 动态代理等复杂场景。例如,当一个 Bean 需要被代理时,Spring 会在三级缓存中通过工厂动态生成代理对象。

三级缓存的工作流程

以下是一个典型的循环依赖解决过程:

  1. 实例化阶段

    • 创建 Bean 的实例(调用无参构造函数),但不进行属性注入。
    • 将该 Bean 的工厂对象(ObjectFactory)放入三级缓存中。
  2. 属性注入阶段

    • 如果当前 Bean 需要依赖另一个 Bean,而该 Bean 尚未完全初始化,则从三级缓存中获取其工厂对象,并生成“早期引用”。
    • 将生成的“早期引用”放入二级缓存中,供当前 Bean 使用。
  3. 初始化阶段

    • 属性注入完成后,执行 Bean 的初始化方法(如 @PostConstruct 或 InitializingBean.afterPropertiesSet())。
    • 初始化完成后,将该 Bean 从二级缓存移动到一级缓存,并清除三级缓存和二级缓存中的相关记录。

2.为什么需要三级缓存?一级和二级不够吗?

一级缓存的问题
  • 一级缓存只能存储完全初始化后的 Bean。如果在初始化过程中发生循环依赖,无法从一级缓存中获取尚未完全初始化的 Bean。
二级缓存的问题
  • 二级缓存可以存储“早期引用”,但如果涉及动态代理(如 AOP),则需要额外的机制来生成代理对象。二级缓存无法动态生成代理对象,因此需要三级缓存。
三级缓存的优势
  • 三级缓存通过工厂模式动态生成代理对象,确保在复杂的依赖关系中,Bean 的状态一致且正确。
  • 三级缓存的设计使得 Spring 能够支持更多的扩展功能(如 AOP 动态代理)。

三级缓存的好处和坏处

好处
  1. 支持复杂的依赖关系

    三级缓存允许在 Bean 的生命周期中动态生成代理对象(如 AOP 动态代理),从而支持更复杂的场景。
  2. 保证线程安全

    三级缓存的设计使得在多线程环境下,Bean 的创建和依赖注入更加安全。
  3. 灵活性

    三级缓存提供了一个灵活的机制,可以在不同阶段对 Bean 的状态进行控制。
坏处
  1. 增加复杂性

    三级缓存的引入增加了代码的复杂性,理解和维护成本较高。
  2. 性能开销

    虽然三级缓存的时间复杂度仍然是 O(1)O(1),但多级缓存的管理会增加一定的性能开销。
  3. 潜在问题

    如果开发者滥用循环依赖,可能导致系统设计不合理,甚至出现难以调试的问题。

3.Spring Boot 高版本为什么要手动开启循环依赖?

背景

在 Spring Boot 2.6 及更高版本中,默认情况下禁用了循环依赖(spring.main.allow-circular-references=false)。这是因为循环依赖虽然可以通过三级缓存解决,但它通常是设计上的问题,可能会导致以下问题:

  1. 代码耦合度过高

    循环依赖通常意味着类之间的职责划分不清晰,容易导致代码难以维护。例如,两个类互相依赖可能表明它们的职责没有很好地分离。
  2. 隐藏设计缺陷

    循环依赖可能掩盖了系统设计中的不合理之处。长期来看,这种设计会导致架构变得复杂且难以扩展。
  3. 测试困难

    循环依赖的 Bean 在单元测试中可能更难模拟和测试,因为它们的依赖关系过于紧密。
  4. 性能问题

    循环依赖的解决需要额外的缓存管理和状态检查,这会增加一定的性能开销。
如何手动开启循环依赖?

在 application.properties 或 application.yml 中设置以下配置:

spring.main.allow-circular-references=true

或者通过代码方式启用:

@SpringBootApplication
public class MyApplication {public static void main(String[] args) {SpringApplication app = new SpringApplication(MyApplication.class);app.setAllowCircularReferences(true);app.run(args);}
}

4.循环依赖的实际案例分析

案例 1:简单的循环依赖

假设有两个类 A 和 B

@Component
public class A {private final B b;@Autowiredpublic A(B b) {this.b = b;}
}@Component
public class B {private final A a;@Autowiredpublic B(A a) {this.a = a;}
}

在这种情况下,Spring 会通过三级缓存解决循环依赖问题。A 和 B 之间的依赖关系会在实例化阶段被正确处理。

案例 2:涉及动态代理的循环依赖

假设 A 是一个事务管理的 Bean,Spring 会为其生成动态代理对象:

@Component
public class A {private final B b;@Autowiredpublic A(B b) {this.b = b;}@Transactionalpublic void doSomething() {// 事务逻辑}
}@Component
public class B {private final A a;@Autowiredpublic B(A a) {this.a = a;}
}

在这种情况下,Spring 会通过三级缓存中的工厂对象动态生成 A 的代理对象,从而解决循环依赖问题。


5.循环依赖的替代方案

为了避免循环依赖,可以采用以下替代方案:

引入中间层

  • 将共同的逻辑抽取到一个新的服务类中,减少直接依赖。
  • @Service
    public class CommonService {public void commonLogic() {// 共同逻辑}
    }@Component
    public class A {private final CommonService commonService;@Autowiredpublic A(CommonService commonService) {this.commonService = commonService;}
    }@Component
    public class B {private final CommonService commonService;@Autowiredpublic B(CommonService commonService) {this.commonService = commonService;}
    }
    

使用事件驱动机制

  • 使用 Spring 的事件发布机制(ApplicationEvent)来解耦组件。
  • @Component
    public class A {@Autowiredprivate ApplicationEventPublisher eventPublisher;public void doSomething() {eventPublisher.publishEvent(new CustomEvent(this));}
    }@Component
    public class B {@EventListenerpublic void handleCustomEvent(CustomEvent event) {// 处理事件}
    }
    

使用懒加载(@Lazy 注解)

  • 通过 @Lazy 注解延迟 Bean 的初始化,从而避免循环依赖问题。
  • @Component
    public class A {private final B b;@Autowiredpublic A(@Lazy B b) {this.b = b;}
    }@Component
    public class B {private final A a;@Autowiredpublic B(@Lazy A a) {this.a = a;}
    }
    

重构代码逻辑

  • 如果两个类之间存在循环依赖,可能表明它们的职责划分不清晰。可以通过重构代码来消除直接依赖。
  • @Service
    public class A {private final CommonLogic commonLogic;@Autowiredpublic A(CommonLogic commonLogic) {this.commonLogic = commonLogic;}public void doSomething() {commonLogic.performLogic();}
    }@Service
    public class B {private final CommonLogic commonLogic;@Autowiredpublic B(CommonLogic commonLogic) {this.commonLogic = commonLogic;}public void doSomethingElse() {commonLogic.performLogic();}
    }@Component
    public class CommonLogic {public void performLogic() {// 共同逻辑}
    }
    

    6.最终总结

    • 循环依赖的本质

      • 循环依赖是指两个或多个 Bean 之间相互依赖,形成一个闭环。
      • Spring 通过三级缓存机制解决了循环依赖问题。
    • 三级缓存的作用

      • 一级缓存:存储完全初始化后的 Bean。
      • 二级缓存:存储“早期引用”(尚未完全初始化的 Bean)。
      • 三级缓存:存储工厂对象,用于动态生成代理对象或其他扩展功能。
    • 为什么需要三级缓存?

      • 一级缓存无法解决循环依赖,因为它只存储完全初始化后的 Bean。
      • 二级缓存无法支持动态代理等复杂场景,因此需要三级缓存。
    • Spring Boot 高版本默认禁用循环依赖的原因

      • 推动更好的设计,避免代码耦合度过高。
      • 减少潜在问题,提高系统性能。
    • 如何手动开启循环依赖?

      • 通过配置文件或代码方式启用 spring.main.allow-circular-references=true
    • 最佳实践

      • 尽量避免循环依赖,采用重构代码、引入中间层或事件驱动机制等方式解决问题。
      • 如果确实无法避免循环依赖,确保它不会导致系统设计问题,并且只在必要的场景下使用。


    文章转载自:

    http://hEHguaQD.kjynz.cn
    http://zpwQzoh0.kjynz.cn
    http://0Je9Yne2.kjynz.cn
    http://jbIAgtkL.kjynz.cn
    http://0C7G5BlG.kjynz.cn
    http://8pUiQdjh.kjynz.cn
    http://izu3i99W.kjynz.cn
    http://NJRRUkOa.kjynz.cn
    http://PaS41iaG.kjynz.cn
    http://LD27dKm8.kjynz.cn
    http://kWaotTBF.kjynz.cn
    http://jajzaZ1j.kjynz.cn
    http://QsM53mCd.kjynz.cn
    http://eOCOTBR7.kjynz.cn
    http://yzl0n8fK.kjynz.cn
    http://NH4KCADg.kjynz.cn
    http://l5HwzHW5.kjynz.cn
    http://thBGFcwF.kjynz.cn
    http://sILOkLqS.kjynz.cn
    http://FAFKKw8i.kjynz.cn
    http://Wyem8VAq.kjynz.cn
    http://xUDL0Exu.kjynz.cn
    http://VzIRMGmn.kjynz.cn
    http://cSmA3nYU.kjynz.cn
    http://XJluwnfi.kjynz.cn
    http://k2mLFGSs.kjynz.cn
    http://ZSxvvqwK.kjynz.cn
    http://Tk64RJmu.kjynz.cn
    http://D31mlhHM.kjynz.cn
    http://zt1XR9J5.kjynz.cn
    http://www.dtcms.com/wzjs/755616.html

    相关文章:

  • 网站建设工资怎么样合肥企业网站建设专家
  • 网站建设维护公司地址永定路网站建设
  • 织梦网站采集如何做济南腾飞网络科技有限公司
  • 手机网站打开微信登录wordpress无法发送
  • 公司网站改版方案管理咨询公司服务口碑好
  • 百度网站名称网页与网站设计说明
  • 自己建网站做代理商顺德微信网站建设
  • 二级网站怎么建做网站服务器系统
  • 英文公司网站建设上海人才网
  • 导航网站前端模板延吉做网站
  • 烟台网站建设找企汇互联专业广告网站留电话
  • 给别人做网站挣钱么wordpress友情链接图像地址
  • seo关键词排名优化要多少钱seo排名规则
  • 网站定制开发怎么写免费做ppt的网站有哪些
  • 凡科免费网站能用吗网站建设前期准备方案
  • 一个小型网站开发成本建设银行个人登录网站
  • 备案 网站错了烟台h5网站建设公司
  • 广州做鞋的网站做网站需要钱吗
  • 上海公司建设网站wordpress js代码编辑器插件下载地址
  • 深圳市坪山新区建设局网站十堰最新新闻今天
  • 福州微信网站制作有没有网站可以做试卷
  • 网站建设 中企动力南昌0792拉新推广怎么找渠道
  • 网站空间租用有哪些服务所得税 网站建设费
  • 网站开发图片存哪里域名注册推荐
  • 企业网站服务器跟域名都需要交钱吗1688app官方下载
  • 学习网站建设总结wordpress主题下载资源
  • 海城网站设计怎么做扫码进入网站
  • 网站添加设置着陆页全国网站设计排名
  • 哪个网站财经做的最好jsp做的网站可以用的
  • 凡科登陆网站手机版网站推广优化趋势