In the chapter about Initialization callbacks, the Spring documentation states
[
@PostConstruct
and other methods] allows a bean to perform
initialization work after all necessary properties on the bean have
been set by the container.
With your commented code, the following happens: beanA
is instantiated and saved. The container sees that all necessary properties have been set and it invokes the init (@PostConstruct
) method. Then it goes to beanB
which it initializes, saves, sees an @Autowired
, retrieves the saved beanA
, injects it, the runs beanB
‘s @PostConstruct
since all its properties have been set.
In your uncommented code, you have a case of circular dependencies. beanA
gets instantiated first and is saved. The container notices it has an injection target of type BeanB
. To perform this injection, it needs the beanB
bean. It therefore instantiates the bean, saves it, sees that it has a dependency on a beanA
as an injection target. It retrieves the beanA
(which was saved earlier), injects it, then beanB
‘s properties are all set and its @PostConstruct
method is invoked. Finally, this initialized beanB
bean is injected into beanA
, whose @PostConstruct
method is then invoked since all its properties have been set.
This second has case beanB
being constructed while beanA
is being constructed. This is how Spring solves the following
class A {
private B b;
}
class B {
private A a;
}
An instance of each has to be created before either can be injected into the other.
If you get rid of the @DependsOn
, you’ll get the same behavior (but just because of the default ordering of classpath scanning, which seems to be alphabetical). If you renamed BeanA
to BeanZ
, for example, the beanB
will be instantiated first, then beanZ
would get instantiated, initialized, and returned to be injected into beanB
.
@DependsOn
is really only necessary if you have side effects that you’d like to happen before a bean is initialized.