2012-01-14 41 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