春季新手:豆装和布线流

时间:2012-01-14 10:29:08

标签: spring autowired

我刚刚开始阅读“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 setter(甚至在加载test2之前)!

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

1 个答案:

答案 0 :(得分:2)

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

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

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

原型范围有点棘手,因为它的行为会有所不同,具体取决于你的原型范围bean是否是代理。

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

但是如果在另一个 singleton bean的应用程序上下文中引用了原型范围的bean,则会注入代理。此代理甚至会为其上的每个方法调用切换实际调用的实例。这会更加恼人:

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

但请核实一下,因为这就是我认为它正在做的事情。我没有通过代码验证它。