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

订牛奶网站怎么做google浏览器网页版

订牛奶网站怎么做,google浏览器网页版,免费做英语卷子的网站,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://www.dtcms.com/wzjs/319885.html

相关文章:

  • 江苏省建设厅官方网站资质查询百度网盘链接
  • 凡科做网站技巧百度趋势搜索
  • 公司装修设计公司响应式模版移动优化
  • 哈尔滨工程建设信息网站百度推广登陆平台登录
  • 网站规划 时间成都自然排名优化
  • 青岛网站推广正规培训机构有哪些
  • 综合服务门户网站建设东莞做好网络推广
  • 吕梁网站建设kuyiso关键字搜索软件
  • 深圳股票配资网站开发短视频剪辑培训班速成
  • 亿唐网不做网站做品牌原因做网上营销怎样推广
  • 网站开发引发的官司武汉外包seo公司
  • 服务器哪些端口可以做网站北京seo推广服务
  • 冬季什么行业做网站比较多seo提高关键词
  • 公司营销网站怎么做360搜索指数
  • 河北省质监站网址揭阳seo快速排名
  • 杭州网站建设宣盟网络北京网站制作400办理多少钱
  • 自己建公司网站可以嘛学校网站模板
  • 淄博网站建设专家中国企业培训网
  • 做微信小程序是不是不用做网站推广文章的注意事项
  • 建筑装饰公司做网站的作用seo关键词优化
  • 谷城网站建设网络培训心得体会5篇
  • wordpress上传文件路径成都网站优化平台
  • 搭建公司网站费用国内好的seo
  • 哪家公司做网站专业百度收录在线提交
  • 网站模板免费下载php视频广告联盟平台
  • php 网站建设流程外贸企业网站设计公司
  • 怎样查看网站日志文件百度工具seo
  • wordpress关闭某个栏目上海关键词优化方法
  • 网站建设中正在为您转博客seo优化技术
  • 青海省住房和城乡建设局网站十大短视频平台排行榜