2012-01-14 43 views
3

我刚刚开始阅读“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 

如果我改变测试范围1原型我得到:

start1 
test2 - setter 
start2 
start1 
test1 - setter 
start1 
test1 - setter 
test2 - getter 
test1 - getter 
End - null 

我知道我的要求太高了,但是有人能让我知道这里涉及的步骤 - 我无法理解为什么在完成tst1的加载(甚至在加载test2之前)之后调用test2 setter!

其次,为什么原型和默认范围的“结束”输出不同? 谢谢。

回答

2

因为Spring首先设置了对其他bean的引用。 (布线的豆) 之后,将调用init方法。

由于您的test2 setter指向您的应用程序上下文配置中的test1引用,因此它将首先被调用。

---------- ------------编辑

原型范围是有点棘手,因为它取决于如果你的原型作用域的bean的行为不同是否代理。

如果您直接从应用程序上下文中获取原型bean,就像您一样,每次都会得到一个新实例。为第一个实例设置一个名称不会影响您在最后写出的第二个实例的名称。

但是,如果在另一个bean的应用程序上下文中引用了原型scoped bean,则会注入一个代理。这个代理甚至会为每个调用方法调用实际调用的实例。这将是更令人讨厌,因为:

Test1 t4 = t3.getName(); 
t4.setName1("lala"); 
assertEquals(null,t4.getName1()); //will be true 

但请验证,因为那就是我认为它正在做。我没有通过代码验证它。

+0

谢谢Omnaest。是否像构造函数和init-methods在连线(setter方法)之后被调用?对我来说似乎很陌生...为什么不被称为摧毁方法? – SlowAndSteady 2012-01-14 11:10:21

+0

可能你杀了JVM,并且不关闭应用程序上下文。后一种行动要求销毁方法。 – Omnaest 2012-01-14 19:36:00