我刚刚开始阅读“Spring In Action-第三版”,并在尝试接线概念时陷入困境。编写以下代码后,我无法理解bean的生命周期:
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");
}
}
这是我的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>
输出为:
start1
test2 - setter
start2
test1 - setter
test1 - setter
test2 - getter
test1 - getter
End - Lin
如果将Test1范围更改为原型,则会得到:
start1
test2 - setter
start2
start1
test1 - setter
start1
test1 - setter
test2 - getter
test1 - getter
End - null
我知道我要求太多,但是有人可以让我了解这里涉及的步骤-我无法理解为什么在tst1加载完成后(甚至在加载test2之前)调用test2 setter!
其次,为什么原型和默认范围的“End”输出不同?
谢谢。
最佳答案
因为Spring确实会首先设置对其他bean的引用。 (豆类接线)
之后,将调用init方法。
由于您的test2设置器指向应用程序上下文配置中的test1引用,因此将首先调用它。
- - - - - 编辑 - - - - - -
原型作用域有点棘手,因为它的行为取决于原型作用域的bean是否是代理。
如果像您一样直接从应用程序上下文中获取原型Bean,则每次都会获得一个新实例。为第一个实例设置名称不会影响您最后写出的第二个实例的名称。
但是,如果在应用程序上下文中从另一个单例bean引用了原型范围的bean,则会注入代理。该代理甚至会为它上的每个方法调用切换实际调用的实例。由于以下原因,这将更加令人讨厌:
Test1 t4 = t3.getName();
t4.setName1("lala");
assertEquals(null,t4.getName1()); //will be true
但是请验证一下,因为那是我想它正在执行的操作。我没有通过代码验证它。