24.再议循环依赖

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.探寻源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值