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

超酷的网站设计珠海网站设计报价

超酷的网站设计,珠海网站设计报价,房产中介公司网站源码,网站建设服务收费标准引言 在复杂的应用开发中#xff0c;循环依赖是一个常见的问题。简单来说#xff0c;循环依赖是指两个或多个Bean之间互相依赖#xff0c;导致程序无法正常实例化这些Bean。Spring容器通过依赖注入#xff08;DI#xff09;来管理Bean的创建与生命周期#xff0c;并在遇… 引言 在复杂的应用开发中循环依赖是一个常见的问题。简单来说循环依赖是指两个或多个Bean之间互相依赖导致程序无法正常实例化这些Bean。Spring容器通过依赖注入DI来管理Bean的创建与生命周期并在遇到循环依赖时采取了多种策略进行处理。本篇文章将带你实现三种解决循环依赖的方式包括构造函数注入、Setter注入和ObjectFactory方式并对比Spring的循环依赖处理机制帮助你理解不同的处理方式及其应用场景。 什么是循环依赖 循环依赖Circular Dependency是指两个或多个Bean互相依赖导致它们无法正常实例化。通常情况下Spring通过依赖注入来管理Bean的生命周期当遇到循环依赖时Spring必须采取额外的策略来解决这个问题。 常见的循环依赖类型 构造函数循环依赖 两个Bean通过构造函数相互依赖导致它们在实例化时陷入循环。 Setter方法循环依赖 两个Bean通过Setter方法相互依赖Spring可以通过提前暴露Bean的部分引用来解决这个问题。 ObjectFactory方式 通过ObjectFactory延迟依赖注入避免在Bean创建时立即解决依赖允许Bean先部分创建。 手动实现三种循环依赖的解决方式 为了更好地理解循环依赖的处理方式我们将手动实现三种常见的解决策略构造函数注入、Setter方法注入和ObjectFactory方式。 实现构造函数注入的循环依赖 构造函数注入的循环依赖比较难解决因为它要求所有的依赖在实例化时就已经准备好。下面我们通过一个示例展示构造函数循环依赖的问题。 示例代码 public class ServiceA {private ServiceB serviceB;// 使用构造函数注入ServiceBpublic ServiceA(ServiceB serviceB) {this.serviceB serviceB; // ServiceA依赖于ServiceB}public void doSomething() {System.out.println(ServiceA is doing something...);} }public class ServiceB {private ServiceA serviceA;// 使用构造函数注入ServiceApublic ServiceB(ServiceA serviceA) {this.serviceA serviceA; // ServiceB依赖于ServiceA}public void doSomething() {System.out.println(ServiceB is doing something...);} }public class ConstructorInjectionTest {public static void main(String[] args) {// 手动实例化构造函数依赖会导致循环依赖问题// ServiceA serviceA new ServiceA(new ServiceB(serviceA)); // 这会导致无限递归无法解决} }问题描述 在上面的代码中ServiceA通过构造函数依赖ServiceB同时ServiceB也通过构造函数依赖ServiceA。由于构造函数注入要求在实例化时就提供依赖因此出现了循环依赖问题导致递归创建的错误。 解决方法Setter方法注入 Setter方法注入的循环依赖比构造函数注入要容易解决因为Spring可以提前暴露部分未完成的Bean引用在Bean完全实例化前进行部分注入。 示例代码 public class ServiceA {private ServiceB serviceB;// 通过Setter方法注入ServiceBpublic void setServiceB(ServiceB serviceB) {this.serviceB serviceB; // ServiceA依赖于ServiceB}public void doSomething() {System.out.println(ServiceA is doing something...);} }public class ServiceB {private ServiceA serviceA;// 通过Setter方法注入ServiceApublic void setServiceA(ServiceA serviceA) {this.serviceA serviceA; // ServiceB依赖于ServiceA}public void doSomething() {System.out.println(ServiceB is doing something...);} }public class SetterInjectionTest {public static void main(String[] args) {// 创建实例ServiceA serviceA new ServiceA();ServiceB serviceB new ServiceB();// 通过Setter方法解决循环依赖serviceA.setServiceB(serviceB); // ServiceA依赖ServiceB延迟注入serviceB.setServiceA(serviceA); // ServiceB依赖ServiceA延迟注入// 测试方法调用serviceA.doSomething(); // 输出ServiceA is doing something...serviceB.doSomething(); // 输出ServiceB is doing something...} }解决思路 使用Setter方法注入解决循环依赖问题通过先创建空的Bean对象再通过Setter方法进行依赖注入。Spring能够在部分Bean完成初始化时将其暴露给其他Bean从而解决循环依赖问题。 解决方法ObjectFactory延迟注入 ObjectFactory方式通过延迟注入来解决循环依赖问题。ObjectFactory允许Spring在需要时才创建依赖对象从而避免在Bean初始化时立即解决依赖。 示例代码 import org.springframework.beans.factory.ObjectFactory;public class ServiceA {private ObjectFactoryServiceB serviceBFactory;// 使用ObjectFactory进行延迟注入public ServiceA(ObjectFactoryServiceB serviceBFactory) {this.serviceBFactory serviceBFactory; // 延迟注入ServiceB}public void doSomething() {System.out.println(ServiceA is doing something...);serviceBFactory.getObject().doSomething(); // 当需要时才获取ServiceB} }public class ServiceB {private ObjectFactoryServiceA serviceAFactory;// 使用ObjectFactory进行延迟注入public ServiceB(ObjectFactoryServiceA serviceAFactory) {this.serviceAFactory serviceAFactory; // 延迟注入ServiceA}public void doSomething() {System.out.println(ServiceB is doing something...);serviceAFactory.getObject().doSomething(); // 当需要时才获取ServiceA} }public class ObjectFactoryInjectionTest {public static void main(String[] args) {// 使用ObjectFactory进行延迟注入解决循环依赖问题ObjectFactoryServiceA serviceAFactory () - new ServiceA(() - new ServiceB(serviceAFactory));ObjectFactoryServiceB serviceBFactory () - new ServiceB(serviceAFactory);// 创建ServiceA和ServiceB的实例ServiceA serviceA serviceAFactory.getObject();ServiceB serviceB serviceBFactory.getObject();// 测试方法调用serviceA.doSomething(); // 输出ServiceA is doing something... ServiceB is doing something...serviceB.doSomething(); // 输出ServiceB is doing something... ServiceA is doing something...} }解决思路 ObjectFactory方式通过延迟创建对象的方式解决循环依赖问题。ObjectFactory允许在依赖实际使用时才实例化依赖对象从而打破了Bean初始化时的相互依赖问题。 类图与流程图 为了更好地理解三种解决方式的工作原理我们提供了类图和流程图。 类图 #mermaid-svg-0PDbIlea1tVpCXfF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-0PDbIlea1tVpCXfF .error-icon{fill:#552222;}#mermaid-svg-0PDbIlea1tVpCXfF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0PDbIlea1tVpCXfF .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-0PDbIlea1tVpCXfF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0PDbIlea1tVpCXfF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0PDbIlea1tVpCXfF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0PDbIlea1tVpCXfF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0PDbIlea1tVpCXfF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0PDbIlea1tVpCXfF .marker.cross{stroke:#333333;}#mermaid-svg-0PDbIlea1tVpCXfF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0PDbIlea1tVpCXfF g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-0PDbIlea1tVpCXfF g.classGroup text .title{font-weight:bolder;}#mermaid-svg-0PDbIlea1tVpCXfF .nodeLabel,#mermaid-svg-0PDbIlea1tVpCXfF .edgeLabel{color:#131300;}#mermaid-svg-0PDbIlea1tVpCXfF .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-0PDbIlea1tVpCXfF .label text{fill:#131300;}#mermaid-svg-0PDbIlea1tVpCXfF .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-0PDbIlea1tVpCXfF .classTitle{font-weight:bolder;}#mermaid-svg-0PDbIlea1tVpCXfF .node rect,#mermaid-svg-0PDbIlea1tVpCXfF .node circle,#mermaid-svg-0PDbIlea1tVpCXfF .node ellipse,#mermaid-svg-0PDbIlea1tVpCXfF .node polygon,#mermaid-svg-0PDbIlea1tVpCXfF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0PDbIlea1tVpCXfF .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-0PDbIlea1tVpCXfF g.clickable{cursor:pointer;}#mermaid-svg-0PDbIlea1tVpCXfF g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-0PDbIlea1tVpCXfF g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-0PDbIlea1tVpCXfF .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-0PDbIlea1tVpCXfF .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-0PDbIlea1tVpCXfF .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-0PDbIlea1tVpCXfF .dashed-line{stroke-dasharray:3;}#mermaid-svg-0PDbIlea1tVpCXfF #compositionStart,#mermaid-svg-0PDbIlea1tVpCXfF .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0PDbIlea1tVpCXfF #compositionEnd,#mermaid-svg-0PDbIlea1tVpCXfF .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0PDbIlea1tVpCXfF #dependencyStart,#mermaid-svg-0PDbIlea1tVpCXfF .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0PDbIlea1tVpCXfF #dependencyStart,#mermaid-svg-0PDbIlea1tVpCXfF .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0PDbIlea1tVpCXfF #extensionStart,#mermaid-svg-0PDbIlea1tVpCXfF .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0PDbIlea1tVpCXfF #extensionEnd,#mermaid-svg-0PDbIlea1tVpCXfF .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0PDbIlea1tVpCXfF #aggregationStart,#mermaid-svg-0PDbIlea1tVpCXfF .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0PDbIlea1tVpCXfF #aggregationEnd,#mermaid-svg-0PDbIlea1tVpCXfF .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0PDbIlea1tVpCXfF .edgeTerminals{font-size:11px;}#mermaid-svg-0PDbIlea1tVpCXfF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ServiceA -ServiceB serviceB doSomething() ServiceB -ServiceA serviceA doSomething() ObjectFactoryT T getObject() 解释 ServiceA和ServiceB互相依赖通过ObjectFactory延迟实例化来避免直接的循环依赖。 流程图 #mermaid-svg-XmjsjKk1jCViB7Kd {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XmjsjKk1jCViB7Kd .error-icon{fill:#552222;}#mermaid-svg-XmjsjKk1jCViB7Kd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XmjsjKk1jCViB7Kd .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-XmjsjKk1jCViB7Kd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XmjsjKk1jCViB7Kd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XmjsjKk1jCViB7Kd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XmjsjKk1jCViB7Kd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XmjsjKk1jCViB7Kd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XmjsjKk1jCViB7Kd .marker.cross{stroke:#333333;}#mermaid-svg-XmjsjKk1jCViB7Kd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XmjsjKk1jCViB7Kd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XmjsjKk1jCViB7Kd .cluster-label text{fill:#333;}#mermaid-svg-XmjsjKk1jCViB7Kd .cluster-label span{color:#333;}#mermaid-svg-XmjsjKk1jCViB7Kd .label text,#mermaid-svg-XmjsjKk1jCViB7Kd span{fill:#333;color:#333;}#mermaid-svg-XmjsjKk1jCViB7Kd .node rect,#mermaid-svg-XmjsjKk1jCViB7Kd .node circle,#mermaid-svg-XmjsjKk1jCViB7Kd .node ellipse,#mermaid-svg-XmjsjKk1jCViB7Kd .node polygon,#mermaid-svg-XmjsjKk1jCViB7Kd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XmjsjKk1jCViB7Kd .node .label{text-align:center;}#mermaid-svg-XmjsjKk1jCViB7Kd .node.clickable{cursor:pointer;}#mermaid-svg-XmjsjKk1jCViB7Kd .arrowheadPath{fill:#333333;}#mermaid-svg-XmjsjKk1jCViB7Kd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XmjsjKk1jCViB7Kd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XmjsjKk1jCViB7Kd .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-XmjsjKk1jCViB7Kd .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-XmjsjKk1jCViB7Kd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XmjsjKk1jCViB7Kd .cluster text{fill:#333;}#mermaid-svg-XmjsjKk1jCViB7Kd .cluster span{color:#333;}#mermaid-svg-XmjsjKk1jCViB7Kd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XmjsjKk1jCViB7Kd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 解决循环依赖 依赖ServiceB ServiceB实例化 依赖ServiceA 解释 使用ObjectFactory延迟注入的方式ServiceA和ServiceB可以在需要时获取对方的实例避免了直接的循环依赖问题。 Spring中的循环依赖处理机制 在Spring中循环依赖的处理是通过多种策略实现的主要包括三级缓存机制。Spring容器通过提前暴露未完成的Bean实例、延迟依赖注入等方式解决循环依赖。 Spring的三级缓存机制 Spring容器内部通过三级缓存来处理循环依赖问题 1 . 一级缓存存储完全初始化好的单例Bean。 2. 二级缓存存储部分实例化、但尚未完成初始化的Bean。 3. 三级缓存存储可以通过代理对象获取的Bean用于解决复杂的循环依赖场景。 当Spring遇到循环依赖时能够通过三级缓存中的代理对象提前暴露未完成的Bean从而解决依赖问题。 源码解析Spring如何解决循环依赖 Spring在DefaultSingletonBeanRegistry类中通过addSingletonFactory()方法提前暴露创建中的Bean来解决循环依赖。 protected void addSingletonFactory(String beanName, ObjectFactory? singletonFactory) {synchronized (this.singletonObjects) {if (!this.singletonObjects.containsKey(beanName)) {this.singletonFactories.put(beanName, singletonFactory); // 将未完成的Bean放入三级缓存this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}} }对比分析手动实现与Spring的区别 Spring的实现 Spring采用了三级缓存的机制通过提前暴露Bean的引用来解决循环依赖。它能够处理复杂的依赖关系和代理对象。三级缓存是Spring容器处理循环依赖的核心策略通过将未完成的Bean放入三级缓存可以提前暴露这些Bean的引用。 手动实现 我们的手动实现展示了三种常见的循环依赖解决方式虽然能够处理基本的循环依赖问题但缺乏Spring的高级功能如三级缓存和生命周期管理。 总结 通过实现构造函数注入、Setter方法注入和ObjectFactory延迟注入三种解决循环依赖的方式你应该对循环依赖的解决策略有了更深入的理解。在Spring框架中三级缓存机制是其处理循环依赖的核心策略它能够灵活地解决复杂的依赖关系。理解这些机制将帮助你在实际开发中更好地管理Bean的生命周期并在需要时解决循环依赖问题。 互动与思考 你是否在项目中遇到过循环依赖问题你更倾向于使用哪种解决策略欢迎在评论区分享你的经验与见解 如果你觉得这篇文章对你有帮助请别忘了 点赞 ⭐收藏 关注 让我们一起深入学习Spring框架成为更优秀的开发者
http://www.hkea.cn/news/14468552/

相关文章:

  • 明年做那些网站能致富微信运营管理软件
  • 网站平台建设成本网站建设教程在线
  • 一个服务器下怎么做两个网站吗一灯wordpress主题
  • 电商网站开发需求文档中小型网站建设 教案
  • 专业购物网站建设工程合同在性质上属于什么合同
  • 广告设计公司宣传文案潍坊seo网站推广
  • 网站宣传工作海南建设网站
  • 做网站海报拓者设计吧室内设计官网案例
  • 网站建设公司哪家好 干净磐石网络成品网站源码免费
  • p2p网站建设 上海WordPress浏览计数插件
  • 文化类网站建设方向老家装设计网
  • 微餐饮网站建设比较好网站上传后 后台进不去
  • 群晖nas 做网站网站没有关键词的弊端
  • 建网站维护需要多少钱专业设计公司vi设计
  • c 网站开发 书鸿运网站建设
  • 沧州做网站价格小型装修公司店面装修
  • 动软代码生成器 做网站找人做网站排名优化
  • 广西南宁市有公司网站设计天津个人做网站
  • 做风控的网站淘宝店铺怎么免费推广
  • php网站怎么做302电子商务网站的实施包括哪些步骤
  • 做期货网站建设工程质量检测机构主管网站
  • 网站刷流量有什么用楼盘销售管理网站开发资源
  • 做购物比价的网站有哪些厦门手机网站
  • 网站如何自动手机版深圳宝协建设公司
  • 人才网网站建设方案天津电力建设公司网站
  • 图书馆第一代网站建设西安流调轨迹公布
  • 建设电影网站的目的WordPress导航主页
  • 那个网做网站便宜建设部注册师网站
  • 石家庄建站公司深信服对单一网站做限速
  • 广东网站开发费用目前网站开发技术