在我们的开发中 , 会不可避免的遇到Bean之间循环依赖的 , 所谓循环依赖 , 就是两个或者两个以上的Bean互相持有对方 , 这样在程序运行调用中 , 会出现这种循环依赖的现象 , 假设是两个Bean , 当程序调用Bean A时 , Bean A中依赖Bean B , 在Bean A中调用Bean B时 , Bean B中又依赖了Bean A , 这样就形成了循环依赖 , 如下图:
文章插图
先从一个小例子来说明 , 使用Spring框架如果出现循环依赖 , 会正常运行吗?下例是在Spring Boot的基础上构建的 。
代码结构如下:
文章插图
程序访问入口是HelloController , 它里面调用了HelloService1:
package com.pig.employee.controller; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMApping;import org.springframework.web.bind.annotation.RestController; import com.pig.employee.service1.HelloService1; @RestControllerpublic class HelloController {@Autowired HelloService1 helloService1;@RequestMapping("/hello") public String sayHello() {return helloService1.say1(); }}看一下HelloService1对应的实现类:
package com.pig.employee.service1.impl; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service; import com.pig.employee.service1.HelloService1;import com.pig.employee.service2.HelloService2;@Service("helloService1")public class HelloService1Impl implements HelloService1 {@Autowired private HelloService2 helloService2;@Override public String say1() {System.out.println(helloService2.toString());return helloService2.say2(); } }实现类中依赖了HelloService2 , 再来看一下HelloService2的实现类:
package com.pig.employee.service2.impl; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service; import com.pig.employee.service1.HelloService1;import com.pig.employee.service2.HelloService2;@Service("helloService2")public class HelloService2Impl implements HelloService2 {@Autowired private HelloService1 helloService1;@Override public String say2() {System.out.println(helloService1.toString());return "helloService2 say hello"; } }【Spring框架是怎么解决Bean之间的循环依赖的】HelloService2的实现类中又依赖了HelloService1 , 这样就形成了循环依赖 , 依托于Spring框架 , 这样的循环依赖能运行成功吗?废话不多说 , 直接运行不就出答案了 , 启动EmployeeApplication:
文章插图
启动没有问题 , 再来访问一下 , 浏览器输入:http://localhost:8080/hello
文章插图
成功访问 , 再来看一下控制台 , 两个Bean也都已经实例化:
文章插图
上面的简单例子可以说明Spring框架可以解决Bean之间循环依赖的 , 下面就来探究Spring是怎么做到的?
对于Spring中Bean的管理 , 下图一目了然:
文章插图
先调用构造函数进行实例化 , 然后填充属性 , 再接着进行其他附加操作和初始化 , 正是这样的生命周期 , 才有了Spring的解决循环依赖 , 这样的解决机制是根据Spring框架内定义的三级缓存来实现的 , 也就是说:三级缓存解决了Bean之间的循环依赖 。我们从源码中来说明 。
先来看Spring中Bean工厂是怎么获取Bean的(AbstractBeanFactory中):
文章插图
文章插图
文章插图
文章插图
一级一级向下寻找 , 找出了前面提到的三级缓存 , 也就是三个Map集合类:
singletonObjects:第一级缓存 , 里面放置的是实例化好的单例对象;
推荐阅读
- 从 Spring Boot 程序启动深入理解 Netty 异步架构原理
- 龙井是不是绿茶,雨前西湖龙井
- 大学生|HR坦言,这2类学生会被直接淘汰,学历都不去看,到底是何原因
- 秦武王死后谁当王 秦武王是怎么死的历史上
- 曹操是个什么样的人?为什么 曹操到底是一个什么样的人呢
- 真是的纪晓岚 纪晓岚传记
- 材质不的各类茶具,明清时期茶具的种类材质是怎样的
- 什么是双重性格 双重性格的原因
- 半壶清茗了相思,高桥银峰绿茶香高味醇汤清叶绿是其怪异的品质特征
- 鲁智深的性格特点是什么