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

wordpress 全站密码网站建设华科技

wordpress 全站密码,网站建设华科技,做文学网站用什么域名,建立网站要钱吗?循环依赖是什么? 想象两个朋友,小明 和 小王: • 小明 说:“在 小王 帮我之前,我无法开始工作。”• 小王 说:“在 小明 帮我之前,我无法开始工作。”这就形成了一个死锁,因为双方都…

循环依赖是什么?

想象两个朋友,小明 和 小王:

  • • 小明 说:“在 小王 帮我之前,我无法开始工作。”

  • • 小王 说:“在 小明 帮我之前,我无法开始工作。”
    这就形成了一个死锁,因为双方都无法在对方未行动的情况下开始。同理,在 Spring Boot 中,当两个或多个 Bean(由 Spring 管理的 Java 对象)直接或间接相互依赖时,就会发生循环依赖,导致 Spring 无法决定先创建哪一个 Bean。

Spring Boot 中的循环依赖简介

在 Spring Boot 中,当两个或多个 Bean 相互依赖(直接或间接),形成一个依赖循环时,就会出现循环依赖。这种情况会使 Spring 的 IoC(控制反转)容器无法解析,因为它无法确定应先实例化哪个 Bean。这可能会导致运行时问题。

循环依赖示例

假设有两个类,ClassA 和 ClassB

  • • ClassA 依赖 ClassB

  • • ClassB 依赖 ClassA

@Component
public class ClassA {private final ClassB classB;@Autowiredpublic ClassA(ClassB classB) {this.classB = classB;}
}@Component
public class ClassB {private final ClassA classA;@Autowiredpublic ClassB(ClassA classA) {this.classA = classA;}
}

在这种情况下,Spring 无法决定先创建 ClassA 还是 ClassB,因为它们彼此需要对方先被实例化。

另一个示例

假设有两个服务类:ServiceA 和 ServiceB

@Service
public class ServiceA {private final ServiceB serviceB;@Autowiredpublic ServiceA(ServiceB serviceB) {this.serviceB = serviceB;}
}@Service
public class ServiceB {private final ServiceA serviceA;@Autowiredpublic ServiceB(ServiceA serviceA) {this.serviceA = serviceA;}
}

在这里:

  • • ServiceA 需要 ServiceB 先被创建。

  • • ServiceB 需要 ServiceA 先被创建。
    这就形成了循环依赖,Spring 不知道应从哪个开始。

为什么这是个问题?

Spring Boot 使用依赖注入来管理 Bean。在启动时,它会尝试创建所有 Bean 并注入它们的依赖。如果存在循环依赖:

  1. 1. Spring 尝试创建 ServiceA,但需要 ServiceB

  2. 2. Spring 接着尝试创建 ServiceB,但需要 ServiceA
    这会陷入无限循环,最终 Spring 会抛出错误。

如何解决循环依赖?

以下是几种解决方法:

1. 使用 Setter 或字段注入

与其使用构造器注入,可以使用 Setter 或字段注入。这允许 Spring 先创建 Bean,然后再注入依赖。

@Service
public class ServiceA {private ServiceB serviceB;@Autowiredpublic void setServiceB(ServiceB serviceB) {this.serviceB = serviceB;}
}@Service
public class ServiceB {private ServiceA serviceA;@Autowiredpublic void setServiceA(ServiceA serviceA) {this.serviceA = serviceA;}
}
什么是 Setter 注入?

在 Spring Boot 中,依赖注入是通过提供类所需的依赖(其他对象)来实现的。主要有三种方式:

  • • 构造器注入:通过构造器提供依赖。

  • • Setter 注入:通过 Setter 方法提供依赖。

  • • 字段注入:直接注入到字段(不推荐)。

使用构造器注入时,Spring 在启动时尝试创建所有 Bean 及其依赖。如果存在循环依赖,会导致问题。而 Setter 注入允许 Spring 先创建 Bean,再通过 Setter 方法注入依赖,从而打破循环依赖。

使用 Setter 注入解决循环依赖的示例

假设有 UserService 和 NotificationService

@Service
public class UserService {private NotificationService notificationService;@Autowiredpublic void setNotificationService(NotificationService notificationService) {this.notificationService = notificationService;}public void createUser(String username) {System.out.println("用户已创建:" + username);notificationService.sendWelcomeNotification(username);}
}@Service
public class NotificationService {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void sendWelcomeNotification(String username) {System.out.println("发送欢迎通知给:" + username);}
}
Setter 注入如何打破循环依赖?
  1. 1. Spring 先创建 Bean
    Spring 先创建 UserService 和 NotificationService,此时不关心它们的依赖。

  2. 2. 通过 Setter 注入依赖
    创建完成后,Spring 调用 Setter 方法注入依赖,例如将 NotificationService 注入到 UserService 中。

  3. 3. 循环依赖被解决
    因为两个 Bean 已存在,Spring 可以成功注入依赖,避免无限循环。

为什么有效?

构造器注入要求在创建 Bean 时解析所有依赖,而 Setter 注入允许先创建 Bean 再处理依赖,从而打破循环。

2. 使用 @Lazy 注解

通过 @Lazy 注解,Spring 不会在启动时立即实例化 Bean,而是创建一个代理对象(基于 CGLIB 的动态代理)作为占位符。只有在首次访问时才实例化实际 Bean。

@Lazy 如何内部解决循环依赖

假设在 ServiceA 中对 ServiceB 使用 @Lazy

@Component
public class ServiceA {private final ServiceB serviceB;@Autowiredpublic ServiceA(@Lazy ServiceB serviceB) {this.serviceB = serviceB;}
}
内部执行流程
  1. 1. Spring 先初始化 ServiceA

  2. 2. 不是直接注入真实的 ServiceB,而是注入一个 ServiceB 的代理对象。

  3. 3. 该代理对象不会立即调用 ServiceB 的构造器。

  4. 4. Spring 随后单独初始化 ServiceB

  5. 5. 当 ServiceA 调用 ServiceB 的方法时,代理才会触发 ServiceB 的实际创建。

示例
@Service
public class ServiceA {private final ServiceB serviceB;@Autowiredpublic ServiceA(@Lazy ServiceB serviceB) {this.serviceB = serviceB;System.out.println("ServiceA 已初始化");}public void useServiceB() {System.out.println("调用 ServiceB...");serviceB.doSomething();}
}@Service
public class ServiceB {public ServiceB() {System.out.println("ServiceB 已初始化");}public void doSomething() {System.out.println("ServiceB 正在执行操作!");}
}
输出解释
ServiceA 已初始化
// ServiceB 尚未初始化!
调用 ServiceB...
ServiceB 已初始化
ServiceB 正在执行操作!

ServiceA 先创建,但 ServiceB 只有在调用时才被实例化。

3. 使用事件驱动方法

事件驱动方法通过解耦服务来打破循环依赖。

什么是事件驱动方法?

在一个事件驱动架构中:

  • • 一个组件(发布者)在某事件发生时发布事件。

  • • 另一个组件(监听者)监听该事件并执行操作。
    发布者和监听者通过事件通信,无需直接依赖对方。

如何解决循环依赖?

以 UserService 和 NotificationService 为例:

  • • UserService 在创建用户时发布事件。

  • • NotificationService 监听该事件并发送欢迎邮件。
    这样,两个服务之间没有直接依赖,循环被打破。

示例代码

事件类

public class UserCreatedEvent {private String username;private String email;public UserCreatedEvent(String username, String email) {this.username = username;this.email = email;}public String getUsername() { return username; }public String getEmail() { return email; }
}

UserService(发布者)

@Service
public class UserService {private final ApplicationEventPublisher eventPublisher;public UserService(ApplicationEventPublisher eventPublisher) {this.eventPublisher = eventPublisher;}public void createUser(String username, String email) {System.out.println("用户已创建:" + username);eventPublisher.publishEvent(new UserCreatedEvent(username, email));}
}

NotificationService(监听者)

@Service
public class NotificationService {@EventListenerpublic void handleUserCreatedEvent(UserCreatedEvent event) {System.out.println("发送欢迎通知给:" + event.getEmail());}
}
工作原理
  • • UserService 创建用户时发布 UserCreatedEvent

  • • NotificationService 监听到事件并发送邮件。

  • • 两者通过事件通信,无直接依赖。

优点
  • • 解耦:服务之间不再紧密耦合。

  • • 可扩展性:可为同一事件添加更多监听者。

  • • 灵活性:通过添加或移除监听者轻松调整行为。

  • • 避免循环依赖:无直接依赖,自然无循环问题。


文章转载自:

http://snqJ0Z9e.mqzcn.cn
http://Mn9Glqv1.mqzcn.cn
http://10zTTmPe.mqzcn.cn
http://DD4dSGCC.mqzcn.cn
http://9lO6t34j.mqzcn.cn
http://HvLNz41v.mqzcn.cn
http://4bwaVAqK.mqzcn.cn
http://8RodiAeF.mqzcn.cn
http://P0jdNYSG.mqzcn.cn
http://pigZywr4.mqzcn.cn
http://bJhK9npk.mqzcn.cn
http://s3Q33dHd.mqzcn.cn
http://TUEpflQB.mqzcn.cn
http://bAK8dx07.mqzcn.cn
http://SCNl4kKG.mqzcn.cn
http://riErPQ1f.mqzcn.cn
http://D07W7WE0.mqzcn.cn
http://9DmiEKUB.mqzcn.cn
http://TQ3N2sAU.mqzcn.cn
http://NabgUWp2.mqzcn.cn
http://gq5h9pTR.mqzcn.cn
http://8hjhRAV7.mqzcn.cn
http://WvoOrKli.mqzcn.cn
http://ynRsrUyf.mqzcn.cn
http://N0dhe2zy.mqzcn.cn
http://bWI3cWgC.mqzcn.cn
http://aJycVC16.mqzcn.cn
http://TKgkO011.mqzcn.cn
http://ZprYfMaY.mqzcn.cn
http://L3aDGBgk.mqzcn.cn
http://www.dtcms.com/wzjs/722022.html

相关文章:

  • 简述网站建设基本过程自适应网站欣赏
  • 德吉机械东莞网站建设wordpress手机验证码插件
  • 企业seo网站推广公司主页网站怎么做
  • wordpress站点地址没有凡客app官网
  • 网站开发工资有多少网络购物平台
  • 深圳网站制作公司流程图学校网站建设工作总结
  • server2008网站建设it运维需要学什么
  • 从域名到网站网站图片链接到视频怎么做
  • 怎么做淘宝客网站和APP广告制作公司注册
  • 动态视频素材网站成都网站建设全平台
  • 网站建设领导小组dw网页制作试题
  • 企业所得税优惠政策最新2023规定湖北seo整站优化
  • 靖江市住房和城乡建设局的网站安徽省建设厅到底哪个网站
  • 360免费自助建站哈尔滨公共资源交易网建设工程
  • 南京自助建站模板单页面网站做百度推广
  • 网站开发需要多少费用网站评论怎么做的
  • 企业建站个人建站源码智慧校园学生端登录平台
  • 网站建设借鉴春季高考网站建设
  • 网站开发+进度表开发程序员培训班
  • 烟台H5网站设计公司室内设计主要学什么课程
  • 合肥制作网站公司上海建工网站
  • 手机摄影网站首页微信网站系统
  • 互助金融网站制作做海报一般都去什么网站看
  • 做网站黑网站赚钱么么网站开发的售后 维保
  • 中国站免费推广入口百度指数数据分析平台入口
  • 做彩票网站是违法的吗网站优化公司排名
  • 桂林北站到桂林站多远2023年6月份又封城了
  • 温州微网站制作哪里有网站名称价格
  • 许昌建网站官方微信公众号
  • 什么是门户网站建设平台高档vi设计公司