您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

Spring框架是怎么解决Bean之间的循环依赖的

时间:2020-12-14 12:36:02  来源:  作者:

在我们的开发中,会不可避免的遇到Bean之间循环依赖的,所谓循环依赖,就是两个或者两个以上的Bean互相持有对方,这样在程序运行调用中,会出现这种循环依赖的现象,假设是两个Bean,当程序调用Bean A时,Bean A中依赖Bean B,在Bean A中调用Bean B时,Bean B中又依赖了Bean A,这样就形成了循环依赖,如下图:

Spring框架是怎么解决Bean之间的循环依赖的

 

先从一个小例子来说明,使用Spring框架如果出现循环依赖,会正常运行吗?下例是在Spring Boot的基础上构建的。

代码结构如下:

Spring框架是怎么解决Bean之间的循环依赖的

 

程序访问入口是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;
 
@RestController
public 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";
	}
 
}

HelloService2的实现类中又依赖了HelloService1,这样就形成了循环依赖,依托于Spring框架,这样的循环依赖能运行成功吗?废话不多说,直接运行不就出答案了,启动EmployeeApplication:

Spring框架是怎么解决Bean之间的循环依赖的

 

启动没有问题,再来访问一下,浏览器输入:http://localhost:8080/hello

Spring框架是怎么解决Bean之间的循环依赖的

 

成功访问,再来看一下控制台,两个Bean也都已经实例化:

Spring框架是怎么解决Bean之间的循环依赖的

 

上面的简单例子可以说明Spring框架可以解决Bean之间循环依赖的,下面就来探究Spring是怎么做到的?

对于Spring中Bean的管理,下图一目了然:

Spring框架是怎么解决Bean之间的循环依赖的

 

先调用构造函数进行实例化,然后填充属性,再接着进行其他附加操作和初始化,正是这样的生命周期,才有了Spring的解决循环依赖,这样的解决机制是根据Spring框架内定义的三级缓存来实现的,也就是说:三级缓存解决了Bean之间的循环依赖。我们从源码中来说明。

先来看Spring中Bean工厂是怎么获取Bean的(AbstractBeanFactory中):

Spring框架是怎么解决Bean之间的循环依赖的

 


Spring框架是怎么解决Bean之间的循环依赖的

 


Spring框架是怎么解决Bean之间的循环依赖的

 


Spring框架是怎么解决Bean之间的循环依赖的

 

一级一级向下寻找,找出了前面提到的三级缓存,也就是三个Map集合类:

singletonObjects:第一级缓存,里面放置的是实例化好的单例对象;

earlySingletonObjects:第二级缓存,里面存放的是提前曝光的单例对象;

singletonFactories:第三级缓存,里面存放的是要被实例化的对象的对象工厂。

所以当一个Bean调用构造函数进行实例化后,即使属性还未填充,就可以通过三级缓存向外暴露依赖的引用值(所以循环依赖问题的解决也是基于JAVA的引用传递),这也说明了另外一点,基于构造函数的注入,如果有循环依赖,Spring是不能够解决的。还要说明一点,Spring默认的Bean Scope是单例的,而三级缓存中都包含singleton,可见是对于单例Bean之间的循环依赖的解决,Spring是通过三级缓存来实现的。源码是让我们知其然并且知其所以然的最好参考,所以多多阅读源码!



Tags:Spring框架   点击:()  评论:()
声明:本站部分内容来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除,谢谢。
▌相关评论
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
▌相关推荐
在我们的开发中,会不可避免的遇到Bean之间循环依赖的,所谓循环依赖,就是两个或者两个以上的Bean互相持有对方,这样在程序运行调用中,会出现这种循环依赖的现象,假设是两个Bean,当程...【详细内容】
2020-12-14   Spring框架  点击:(0)  评论:(0)  加入收藏
前言学习过Spring框架的人一定都会听过Spring的IOC(控制反转) 这个概念,对于初学Spring的人来说,总觉得IOC是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spr...【详细内容】
2020-12-03   Spring框架  点击:(5)  评论:(0)  加入收藏
1、IOC和DIIOC: 控制反转 即控制权的转移,将我们创建对象的方式反转了,以前对象的创建时由我们开发人员自己维护,包括依赖关系也是自己注入。使用了spring之后,对象的创建以...【详细内容】
2020-11-03   Spring框架  点击:(7)  评论:(0)  加入收藏
今天学习内容安排如下: 切面配置的核心三步骤。 传统sprin配置和AspectJ配置都学下,xml和注解都使用下。 同时为了测试,补充说明一下spring的junit集成,几天前没来得及学的知识...【详细内容】
2020-08-19   Spring框架  点击:(6)  评论:(0)  加入收藏
今天是刘小爱自学Java的第123天。感谢你的观看,谢谢你。 学过很多面向XX编程,比如:面向过程编程,面向对象编程,面向接口编程,现在又是面向切面编程。但是不管如何,说来说去最终都是...【详细内容】
2020-08-15   Spring框架  点击:(2)  评论:(0)  加入收藏
Spring介绍Spring 是一个开源框架,是一个分层的 JavaEE 一站式框架。所谓一站式框架是指 Spring 有 JavaEE 开发的每一层解决方案。 WEB层:SpringMVC Service层:Spring的Bean管...【详细内容】
2020-03-03   Spring框架  点击:(22)  评论:(0)  加入收藏
前言前面一篇文章我讲了一下Web应用程序的基础,主要是基于网络连接的I/O数据处理,为了对网络上传输的数据进行处理,我们首先必须清楚的了解网络传输的数据是二进制数据流由...【详细内容】
2019-12-23   Spring框架  点击:(22)  评论:(0)  加入收藏
什么是Spring Boot框架?什么是Spring框架?他们的目标是什么?他们产生的背景是怎样的,两者有什么区别,我们应该使用哪个框架进行开发,带着这样的疑问,我们开始今天的讲解。 Spring...【详细内容】
2019-12-09   Spring框架  点击:(24)  评论:(0)  加入收藏
一、web应用1.我们生活在web时代,每一分钟都有上百万个网页在生成,包含很多内容web应用是一种客户端-服务器端的程序客户端包括用户界面和客户端逻辑,运行环境为web浏览器2.常...【详细内容】
2019-11-07   Spring框架  点击:(35)  评论:(0)  加入收藏
欢迎关注头条号:Java小野猫首先我们要知道java获得对象的方式有四种:1.通过new语句实例化一个对象。2.通过反射机制创建对象。3.通过clone()方法创建对象3.通过反序列化的方...【详细内容】
2019-08-29   Spring框架  点击:(62)  评论:(0)  加入收藏
spring框架:1.spring是一个轻量级的控制反转和面向切面aop的容器框架控制反转:ioc 核心容器:1.应用上下文 context模块:2.aop模块:3.jdbc抽象和dao模块4.对象关系映射集成模块5.s...【详细内容】
2019-08-12   Spring框架  点击:(195)  评论:(0)  加入收藏
1、使用框架的意义与Spring的主要内容随着软件结构的日益庞大,软件模块化趋势出现,软件开发也需要多人合作,随即分工出现。如何划分模块,如何定义接口方便分工成为软件工程设...【详细内容】
2019-08-08   Spring框架  点击:(55)  评论:(0)  加入收藏
我们在开发项目时,常常会需要支持多国语言,这时就会要求我们的程序支持国际化,也就是可以根据客户端系统的语言类型显示相应的文案与界面。在spring中可以很方便的开发出支持国...【详细内容】
2019-08-07   Spring框架  点击:(58)  评论:(0)  加入收藏
虽然现在流行用SpringBoot了,很多配置已经简化和封装了,但是对于Spring的一些基础我们了解一些是对我们自己的架构思想很有帮助的!接下来和笔者一起来探讨一下Spring框架吧!1...【详细内容】
2019-07-30   Spring框架  点击:(74)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条