我希望Spring在调用@DependsOn
方法时考虑@PostConstruct
,但似乎不存在循环(自动连线)依赖关系的情况。
考虑两个bean(下面的代码),BeanB @DependsOn BeanA
。当字段BeanA#b
将其@Autowired
注释掉时,后构造方法按预期顺序调用:首先是A,然后是B.但是对于A有效@Autowired
,我有B的{{首先调用1}},然后然后 A post
。
我理解这是一个糟糕的设计(实际上,它是非常大的post
...代码库的最小演示),但我期待Spring完成@Autowired
字段和然后开始调用生命周期回调,尊重@Autowired
,但是当有圆形代表时,Spring似乎忽略了@DependsOn
顺序。
Spring版本是4.1.5。
那么,这是我的误解或无证件行为还是可以被视为一个Spring bug (或者,也许是功能请求)?
@DependsOn
答案 0 :(得分:3)
在关于Initialization callbacks的章节中,Spring文档说明了
[
@PostConstruct
和其他方法]允许bean执行 在bean的所有必要属性之后进行初始化工作 由容器设置。
使用您的注释代码,会发生以下情况:beanA
被实例化并保存。容器看到已设置所有必需的属性,并调用init(@PostConstruct
)方法。然后转到beanB
,它会初始化,保存,看到@Autowired
,检索已保存的beanA
,注入它,运行beanB
' s {{1因为已经设置了所有属性。
在未注释的代码中,您有一个循环依赖的情况。首先实例化@PostConstruct
并保存。容器注意到它具有beanA
类型的注射目标。要执行此注入,它需要BeanB
bean。因此,它实例化bean,保存它,看到它作为注入目标依赖于beanB
。它检索beanA
(之前已保存),注入它,然后beanA
的属性都已设置并调用其beanB
方法。最后,这个初始化的@PostConstruct
bean被注入beanB
,然后调用其beanA
方法,因为它已经设置了所有属性。
第二个案例@PostConstruct
正在构建beanB
时构建。这就是Spring如何解决以下问题
beanA
必须先创建每个实例才能将其注入另一个实例。
如果你摆脱了class A {
private B b;
}
class B {
private A a;
}
,你会得到相同的行为(但这只是因为类路径扫描的默认排序,这似乎是按字母顺序排列的)。例如,如果您将@DependsOn
重命名为BeanA
,则BeanZ
将首先实例化,然后beanB
将被实例化,初始化并返回注入{{1} }}
beanZ
实际上只有在你初始化bean之前有你想要的副作用时才是必要的。
答案 1 :(得分:0)
受Sotirios的回答启发并进行了一些调查:
class A {
private B b;
}
class B {
private A a;
}
spring要做的是实例化一个a
和b
,
然后,它为a
执行“设置阶段”。它将设置a.b=b;
,然后将在@PostConstruct
上调用a
方法。
然后为b执行“设置”。它设置b.a=a;
,然后在b上调用@PostConstruct
方法。
因此,如果您仔细查看,在a
的{{1}}时,@PostConstruct
尚未完全设置。就像... b
尚未被分配。
@AutoWired
在b.a
的{{1}}中为空。
显然这是“春天之路”吗?
因此,如果a
的{{1}}调用b @PostConstruct
上的某个方法,则b的循环a
尚未分配,因此最终结果(如果tell_me_about_a调用a @PostConstruct
的方法是一个类似于
b.tell_me_about_a
但是,在a
的{{1}} a
期间,实例已完全启动,并且不缺少其NullPointerException # calling some A method
someLineOfB
somePostConstructMethodOfA
的实例,因此b
不会是NullPointerException。令人困惑...
@PostConstruct
可以更改某些顺序。但似乎与expect的顺序相反。
我认为您是对的,因为它是圆形的,您不能依赖@DependsOn [?],因为它可以按预期的方式运行(如果没有按预期的顺序运行PostConstruct,那么对我来说这就像一个错误。
您可以通过添加spring logging来看到这种行为,然后您会看到诸如b.a
demo
可以解决的方法:
在PostConstruct期间请小心使用注入依赖项的方法。或不打。
完全使用弹簧连接的构造函数参数代替@AutoWired
。在这种情况下,弹簧不允许圆形。无论如何你可能想要...
以相反的顺序使用@DependsOn吗?什么?...