Spring 如何解决循环依赖?

 创作内容丰富的干货文章很费心力,感谢点过此文章的读者,点一个关注鼓励一下作者,激励他分享更多的精彩好文,谢谢大家!


        在关于Spring的面试中,我们经常会被问到一个问题:Spring是如何解决循环依赖的问题的。这个问题算是关于Spring的一个高频面试题,因为如果不刻意研读,相信即使读过源码,面试者也不一定能够一下子思考出个中奥秘。
        本文主要针对这个问题,从源码的角度对其实现原理进行讲解。

循环依赖的简单例子

        比如几个Bean之间的互相引用:

        甚至自己“循环”依赖自己:

原型(Prototype)的场景是不支持循环依赖的

先说明前提:原型(Prototype)的场景是不支持循环依赖的。单例的场景才能存在循环依赖。

        原型(Prototype)的场景通常会走到 AbstractBeanFactory 类中下面的判断,抛出异常。

if (isPrototypeCurrentlyInCreation(beanName)) {
	throw new BeanCurrentlyInCreationException(beanName);
}

        原因很好理解,创建新的A时,发现要注入原型字段B,又创建新的B发现要注入原型字段A...
这就套娃了, Spring就先抛出了BeanCurrentlyInCreationException。
        什么是原型(Prototype)的场景?
        通过如下方式,可以将该类的bean设置为原型模式。

@Service
@Scope("prototype")
public class MyReportExporter extends AbstractReportExporter {
	...
}

        在Spring中,@Service默认都是单例的。

所谓单例,就是Spring的IOC机制只创建该类的一个实例,每次请求,都会用这同一个实例进行处理,因此若存在全局变量,本次请求的值肯定会影响下一次请求时该变量的值。

        若不想影响下次请求,就需要用到原型模式,即@Scope(“prototype”)。

原型模式,指的是每次调用时,会重新创建该类的一个实例,比较类似于我们自己new的对
象实例。

具体例子:循环依赖的代码片段

        我们先看看当时出问题的代码片段:

@Service
publicclass TestService1 {

	@Autowired
	private TestService2 testService2;

	@Async
	public void test1() {
	
	}
}

@Service
publicclass TestService2 {

	@Autowired
	private TestService1 testService1;

	public void test2() {
	
	}
}

        这两段代码中定义了两个Service类: TestService1 和 TestService2 ,在TestService1中注入了TestService2的实例,同时在TestService2中注入了TestService1的实例,这里构成了循环依赖。只不过,这不是普通的循环依赖,因为TestService1的test1方法上加了一个 @Async 注解。
大家猜猜程序启动后运行结果会怎样?

org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testService1': Bean with name 'testService1' has been injected into other beans [testService2] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type mat

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏日彩虹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值