24.再议循环依赖

本文深入探讨了在Spring框架中,如何解决循环依赖问题,特别是在singleton作用域下,通过setter注入方式和提前暴露单例工厂方法来避免死循环。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概念回顾

1. 概念

1. 在本系列,《3.IOC容器》这章中,提到过循环依赖的概念:	A 依赖 B, B 也依赖 A:
        public Class A {
            private B b;

            public A(B b) {
                this.b= b;
            }

            // setter and getter
        }

        public Class B {
            private A a;

            public B(A a) {
                this.a = a;
            }

            // setter and getter
        }

运行时,抛出BeanCurrentlyInCreationException.

2. scope为prototype

  1. 不能使用循环依赖,原因:
// A 依赖 B, B依赖 A: A 创建中,发现需要 B, 去创建 B, B创建中,发现需要 A
// 去创建 A, 由于 scope是 prototype, 会建立一个新的 A, 会发生 stackoverflow?
// 是的,会stackoverflow.
// Method threw 'java.lang.StackOverflowError' exception. Cannot evaluate java.lang.StackOverflowError.toString()

3. scope为 singleton

1. 构造器

无法解决循环依赖: A 构造时,需要 B 的实例, B需要先实例化,B通过构造器实例化,发现需要 A的实例,这显然,陷入了死循环

2. Setter

可以解决循环依赖(但是由于过早曝光,创建出来的实例无任何属性填充、后续处理等,是个”生肉“): 可以先通过 A/B 无参构造构造器把 A/B实例先创建出来,再通过setter扶植给依赖。

2.解决之道

通过Setter方法解决,大致过程如下:
通过提前暴露一个单例工厂方法,从而,其他的bean能够引用到该bean, 如下代码所示:
addSingletonFactory(beanName, new ObjectFactory() {
	public Object getObject() throws BeansException {
		return getEarlyBeanReference(beanName, mbd, bean);
	}
})
具体步骤如下:

1) Spring容器创建单例 A a bean, 首先根据无参构造器创建bean, 并暴露一个ObjectFactory 用于返回一个提前暴露一个创建的bean, 并将 a 标识符放入当前创建bean的池里,然后进行setter,注入 B b.
    
2) Spring创建 单例 B b, 首先根据无参构造器创建 bean 实例 b. 并通过 objectFactory进行暴露对 b的引用。再执行 setter, 这时,需要注入a. 由于1)中 提前暴露了对 a的应用 objectFactory, 可以通过 objectFactory 拿到 a.注入 a. 之后返回 b.
    
3) 最后,a 通过objectFactory 拿到 b, 注入。完成。

3.探寻源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值