I have just started reading “Spring In Action – Third edition” and am stuck up while experimenting with wiring concepts. I am unable to understand the lifecycle of a bean after writing this code :
public class TestCase {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("test.xml");
Test1 t1 = (Test1)context.getBean("test1");
t1.setName1("Win");
Test1 t2 = (Test1)context.getBean("test1");
t2.setName1("Lin");
Test2 t3 = (Test2)context.getBean("test2");
Test1 t4 = t3.getName();
System.out.println("End" +t4.getName1());
}
}
public class Test1 {
private String name1;
public String getName1() {
System.out.println("test1 - getter");
return name1;
}
public void setName1(String name1) {
System.out.println("test1 - setter");
this.name1 = name1;
}
public void onStart()
{
System.out.println("start1");
}
public void onStop()
{
System.out.println("stop1");
}
}
public class Test2 {
private int age;
private Test1 name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Test1 getName() {
System.out.println("test2 - getter");
return name;
}
public void setName(Test1 name) {
System.out.println("test2 - setter");
this.name = name;
}
public void onStart()
{
System.out.println("start2");
}
public void onStop()
{
System.out.println("stop2");
}
}
Here’s my test.xml :
<bean id="test1" class="springidol.Test1" init-method="onStart" destroy-method="onStop" >
</bean>
<bean id="test2" class="springidol.Test2" init-method="onStart" destroy-method="onStop">
<property name="name" ref="test1"></property>
</bean>
The output is :
start1
test2 - setter
start2
test1 - setter
test1 - setter
test2 - getter
test1 - getter
End - Lin
If I change the Test1 scope to prototype I get :
start1
test2 - setter
start2
start1
test1 - setter
start1
test1 - setter
test2 - getter
test1 - getter
End - null
I know I am asking for too much, but can someone get me the steps involved here – I cant understand why test2 setter is getting called after loading of tst1 is done (and even before test2 is loaded) !
Secondly, why are the “End” outputs for prototype and default scopes different ?
Thanks.
Because Spring does set the references to other beans first. (Wiring of the beans)
After that the init methods will be invoked.
Since your test2 setter points to a reference of test1 within your application context configuration it will be invoked first.
———-edit————
The prototype scope is a little bit tricky, since it behaves different depending if your prototype scoped bean is a proxy or not.
If you get the prototyped bean from the application context directly, like you did, you will get a new instance each time. Setting a name to the first instance will not affect the name of the second instance you write out at the end.
But if a prototype scoped bean is referenced within the application context from another singleton bean, a proxy is injected. This proxy will even switch the actually invoked instance for every method call on it. This will be more irritating since:
But please verify that, since thats what I suppose it is doing. I did not verified it by code.