I am currently trying to understand the way in which spring creates and destroys beans and how it comes up with the right order to do so. Lets assume we have three classes
@Component
class Demo1 {
}
@Component
class Demo2{
Demo1 demo1;
// specifically not using @Autowired
public Demo2(Demo1 demo1){
this.demo1 = demo1;
}
public Demo1 getDemo1(){
return this.demo1
}
}
@Component
class Demo3 {
Demo1 demo1
Demo2 demo2;
public Demo3(Demo1 demo1, Demo2 demo2){
this.demo1 = demo1;
this.demo2 = demo2;
}
}
Config class
@Configuration
class MyConfig {
@Bean
public Demo1 demo1(){
return new demo1()
}
@Bean
public Demo2 demo2(){
return new Demo2(demo1());
}
@Bean
public Demo3 demo3(){
Demo2 demo2 = demo2()
return new Demo3(demo2.getDemo1(), demo2);
}
}
I understand that this is not the best/right way to do it but I want to know if its equivalent to using @Autowired
annotation and if spring is able to resolve the dependency among the beans while creation, that is create in order
- demo1
- demo2
- demo3
and destroy in order
- demo3
- demo2
- demo1
Does changing the order of the functions in MyConfig
make any difference ?
Currently I am facing an error where I believe demo1
is getting destroyed before demo2
or demo3
CodePudding user response:
It doesn't matter if you express configuration in XML, properties (yes that is possible, see https://deinum.biz/2018-04-12-on-spring-applicationcontext-and-bean-creation/), java config or annotations. All of those are bean definitions and the relation between those. Spring will have (some kind) of dependency tree.
Beans are constructed in a certain order and destroyed in the reverse order.
The only "wrong" thing in your code is the demo2.getDemo1()
but in this case shouldn't make any difference as Demo3
depends on Demo2 which depends on
Demo1`. Ideally you would write the configuration in the following way
Configuration
class MyConfig {
@Bean
public Demo1 demo1(){
return new demo1()
}
@Bean
public Demo2 demo2(Demo1 demo1){
return new Demo2(demo1);
}
@Bean
public Demo3 demo3(Demo2 demo2, Demo1 demo1){
return new Demo3(demo1, demo2);
}
}
This code/config makes it easier for Spring to figure out the interdependencies.
In your case, if you are using Spring Boot and have declared those @Bean
methods you will actually end up with multiple instances of the beans.
Running your sample produces, for me the following output (I added @PostConstruct
and @PreDestroy
methods to the classes).
2022-09-06 09:03:48.366 INFO 64364 --- [ main] b.d.d.DestructionOrderApplication : No active profile set, falling back to 1 default profile: "default"
biz.deinum.destructionorder.DestructionOrderApplication$Demo1@2fb5fe30 - @PostConstruct
biz.deinum.destructionorder.DestructionOrderApplication$Demo1@389562d6 - @PostConstruct
biz.deinum.destructionorder.DestructionOrderApplication$Demo2@5a101b1c - @PostConstruct
biz.deinum.destructionorder.DestructionOrderApplication$Demo2@2160e52a - @PostConstruct
biz.deinum.destructionorder.DestructionOrderApplication$Demo3@29f0802c - @PostConstruct
biz.deinum.destructionorder.DestructionOrderApplication$Demo3@3a60c416 - @PostConstruct
2022-09-06 09:03:48.559 INFO 64364 --- [ main] b.d.d.DestructionOrderApplication : Started DestructionOrderApplication in 0.311 seconds (JVM running for 0.552)
biz.deinum.destructionorder.DestructionOrderApplication$Demo3@3a60c416 - @PreDestroy
biz.deinum.destructionorder.DestructionOrderApplication$Demo3@29f0802c - @PreDestroy
biz.deinum.destructionorder.DestructionOrderApplication$Demo2@2160e52a - @PreDestroy
biz.deinum.destructionorder.DestructionOrderApplication$Demo2@5a101b1c - @PreDestroy
biz.deinum.destructionorder.DestructionOrderApplication$Demo1@389562d6 - @PreDestroy
biz.deinum.destructionorder.DestructionOrderApplication$Demo1@2fb5fe30 - @PreDestroy
In which you can clearly see the @PostConstruct
is called in the right order and the @PreDestroy
in the reverse order. You can also see you have 2 instances. Removing the @Component
leads to the following output:
2022-09-06 09:06:03.520 INFO 64388 --- [ main] b.d.d.DestructionOrderApplication : No active profile set, falling back to 1 default profile: "default"
biz.deinum.destructionorder.DestructionOrderApplication$Demo1@72ab05ed - @PostConstruct
biz.deinum.destructionorder.DestructionOrderApplication$Demo2@27e32fe4 - @PostConstruct
biz.deinum.destructionorder.DestructionOrderApplication$Demo3@c3c4c1c - @PostConstruct
2022-09-06 09:06:03.714 INFO 64388 --- [ main] b.d.d.DestructionOrderApplication : Started DestructionOrderApplication in 0.32 seconds (JVM running for 0.561)
biz.deinum.destructionorder.DestructionOrderApplication$Demo3@c3c4c1c - @PreDestroy
biz.deinum.destructionorder.DestructionOrderApplication$Demo2@27e32fe4 - @PreDestroy
biz.deinum.destructionorder.DestructionOrderApplication$Demo1@72ab05ed - @PreDestroy