spring ioc部分2个小问题

1 spring在什么情况下会报循环依赖相关的异常?

这个问题似乎很简单,多处资料都会说spring可以通过三级缓存来解决单例模式,setter方法注入的循环依赖问题,对于构造器注入、原型模式的Bean,就会发生异常?那么在一个循环依赖的情况中,其中的Bean 存在(单例/原型)x(setter注入/构造注入),会报异常吗?显然无法套用上面的判断依据。那么我们能否找出一条更为细致的判断依据呢?在经过多次测试对比后,我们得出如下结论:
在循环依赖情况下,当我们通过getBean(“A”)方法获取一个实体时,如果容器已经被容器管理(单例且处于1级缓存)或者,可以在实例化其依赖的属性之前被实例化(setter注入)并被放入容器中(单例此时处于创建过程中,属性未完全填充,处于2/3级缓存),则不会抛出循环依赖相关的异常。
(注意:单例才能被容器管理)。这段话可以解释在具体的环境中,加载顺序不同结果不同。可以试试如下场景:
A —构造器—> B, B —setter—>A(单例A依赖属性B,通过构造器注入;单例B依赖属性A,通过setter方法注入)
case1: getBean(“A”)报错;
case2: getBean(“B”);getBean(“A”)正常
思路:
case1:获得实例A时,如果A已被完整的放入缓存,则返回即可;反之开始创建A,发现通过构造器注入,需要先实例化B,将B作为参数实例化A,在实例化B的过程中,无参构造实例化B,填充B的属性A,发现A正在创建中,抛出异常。(假如B也是构造注入,因为A正在创建的缘故,容器改为无参构造实例化B,然后在填充B时抛异常)
case2: 获得实例B时,如果B已被完整的放入缓存,则返回即可;反之开始创建B,发现通过setter注入A,无惨构造实例化B,将B放入容器3级缓存,然后开始填充其属性A,尝试创建A,发现其依赖B,此时B已经放入容器,可以被拿到,A创建成功(放入容器),因而B属性填充完成。在getBean("B)完成后,A、B已经被放入1级缓存,此时再次访问A,成功。

2 在spring ioc容器和spring mvc容器父子容器条件下,如果父子容器重复配置了某一个单例?那么它一定单例吗?

不一定,举例如下:
ioc 容器配置单例B和A,A依赖属性B。
mvc 仅配置一模一样的单例B。
问:getBean(“B”) == getBean(“A”).getB()为true吗?
答案是否定的,在访问A时,由于mvc容器中没有配置A,会委托给父容器ioc容器,由于A与B的依赖关系,此时也会在ioc容器中实例化B。而在访问B时,B在mvn中有定义,会在mvc中再次实例化。所以答案为false.

发布了28 篇原创文章 · 获赞 11 · 访问量 1530

猜你喜欢

转载自blog.csdn.net/weixin_42881755/article/details/97616209