Source of the problem:
There is one bean A and one bean B. I want to assign an attribute name of A to the return value of a method funB of B when the container is instantiated.
If it is simply written in A:
private B b;
private String name = b.funb();
An error will be reported saying nullpointException, because b has not been set at this time, so it is null.
The solution is the following code, and at the same time learn the execution order of InitializingBean , object construction method and init-method in spring.
public class A implements InitializingBean {
private B b;
private String name; // = b.funb();
public void setB(B b) {
System.out.println("A.setB initialed");
this.b = b;
}
public A() {
System.out.println("A initialed");
}
public void init() {
System.out.println("init");
this.name = b.funb();
}
@Override
public String toString() {
return super.toString() + this.name;
}
public void afterPropertiesSet() throws Exception {
//其实放在这里也可以
//this.name = b.funb();
System.out.println("afterPropertiesSet");
}
}
public class B {
public String funb() {
System.out.println("funb");
return "B.funb";
}
public B() {
System.out.println("B initialed");
}
}
spring configuration file
<beans default->
<bean id="a" class="testspring.A" init-method="init">
</bean>
<bean id="b" class="testspring.B">
</bean>
</beans>
Test code:
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext(
"src/testspring/bean.xml");
A a = (A) context.getBean("a");
System.out.println(a);
}
The program output is:
A initialed
B initialed
A.setB initialed
afterPropertiesSet
init
funb
[email protected]
It can be seen from here that the name attribute of A is successfully set as the return value of the funB method of B when the bean is loaded. The point is to use init-method to achieve it.
The load order can also be seen as:
First constructor -> then b's set method injection -> afterPropertiesSet method of InitializingBean -> init- method method
Summarized as:
The following content is excerpted from the book, but I found that even if it is excerpted once, the understanding of its content will be more in-depth!
First, the process of Spring assembling Bean
1. Instantiate;
2. Set property values;
3. If implemented BeanNameAware interface, call setBeanName to set Bean ID or Name;
4. If BeanFactoryAware interface is implemented, call setBeanFactory to set BeanFactory;
5. If ApplicationContextAware is implemented, call setApplicationContext to set ApplicationContext
6. Call the pre-initialization method of BeanPostProcessor;
7. Call afterPropertiesSet( ) method;
8. Call the custom init-method method;
9. Call the post-initialization method of BeanPostProcessor;