Reputation: 2797
I have a question about auto-wiring order and @PostConstruct
logic in Spring. For example following demo code I have a main Spring Boot class:
@SpringBootApplication
public class Demo1Application {
@Autowired
BeanB beanb;
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
}
and 2 @Service
Definitions:
@Service
public class BeanB {
@Autowired
private BeanA beana ;
@PostConstruct
public void init(){
System.out.println("beanb is called");
}
public void printMe(){
System.out.println("print me is called in Bean B");
}
}
@Service
public class BeanA {
@Autowired
private BeanB b;
@PostConstruct
public void init(){
System.out.println("bean a is called");
b.printMe();
}
}
and I have the following output:
bean a is called
print me is called in Bean B
beanb is called
My question is how autowiring takes place step by step like a scenario above?
And how printMe()
method of beanb
is called without calling its @PostConstruct
first?
Upvotes: 39
Views: 69884
Reputation: 116
It will show class not found exception as class A depends on class B. and class B depends on class A.
Upvotes: 0
Reputation: 3205
Below should be possible sequence
beanb
starts to get autowiredBeanb
, beana starts to get autowired@PostConstruct
i.e. init()
of beana gets calledinit()
, System.out.println("bean a is called");
gets calledb.printMe();
gets called causing System.out.println("print me is called in Bean B");
to executebeana
completed the @PostConstruct
i.e. init()
of beanb
gets calledSystem.out.println("beanb is called");
gets calledIdeally the same can be better observed by a debugger in eclipse.
The Spring reference manual explains how circular dependencies are resolved. The beans are instantiated first, then injected into each other.
Upvotes: 26
Reputation: 6836
Your Answer is Correct as you shown in Your question.
Now Getting the concept of Notation @Autowired
. All @Autowired
Objects are initialized and loaded in memory just after class Loading is done.
Now here is your SpringBootApplication
@SpringBootApplication
public class Demo1Application {
@Autowired
BeanB beanb; // You are trying to autowire a Bean class Named BeanB.
Here at above Console Application that you have write try to autowire and inject a object of type BeanB
.
Now here is your definition of BeanB
@Service
public class BeanB {
@Autowired
private BeanA beana ;
In BeanB
class you are trying to inject the Object of Class BeanA
which is also defined in your console Project.
So, In Your Demo1Application
to inject a Object of Class BeanB
there must need to inject a Object of class BeanA
.
Now BeanA
Class Object is Created First.
Now if you see the definition of Your Class BeanA
@Service
public class BeanA {
@Autowired
private BeanB b;
@PostConstruct // after Creating bean init() will be execute.
public void init(){
System.out.println("bean a is called");
b.printMe();
}
}
So, After injecting the Object BeanA
method bind with @PostContruct
annotation is going to execute.
So, execution flow will be..
System.out.println("bean a is called");
System.out.println("print me is called in Bean B");
System.out.println("beanb is called");
Upvotes: 6