學習Spring(六) -- Spring中Bean的做用域以及生命週期

Bean的做用域java

    默認狀況下,bean的做用域爲單例模式(singleton):spring

  1. 在applicationContext建立時,就將配置文件中的bean加載完畢;app

  2. 在調用getBean時,從applicationContext中獲取;less

    也就是說,在整個應用程序中,bean只存在一個實例,下面寫一段代碼測試一下,寫一個Car類,有一個Name字段:ide

package cn.net.bysoft.lesson4;

public class Car {

    public Car() {
    }

    @Override
    public String toString() {
        return "Car [name=" + name + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String name;

}

    在配置文件中,配置這個Car的bean元素:函數

<bean id="car" class="cn.net.bysoft.lesson4.Car">
</bean>
@Test
    public void testScopeIsDefault() {
        // 在Spring容器初始化時就生成了bean對應的對象。

        // 在調用時,從Spring容器中get一個對象,這個對象是單例的。
        Car car = (Car) ctx.getBean("car");
        car.setName("Audi");

        Car car1 = (Car) ctx.getBean("car");
        car1.setName("BMW");

        // get到的對象都會修改這個單例的bean。
        System.out.println(car);
        System.out.println(car1);

        /**
         * output: 
         * Car [name=BMW] 
         * Car [name=BMW]
         * */
    }

    測試發現,對car設置的name值被car1覆蓋了,也就是說,car與car1實際是使用的同一個car實例,car==car1。post

    能夠改變bean的做用域來解決此問題,將scope=prototype:測試

<bean id="car2" class="cn.net.bysoft.lesson4.Car" scope="prototype">
</bean>
@Test
    public void testScopeIsPrototype() {
        // 設置了bean的scope=prototype後
        // 在Spring容器初始化時不會自動生成bean對應的對象
        // 而是在get時生成對象,對象不是單例的。
        Car car = (Car) ctx.getBean("car2");
        car.setName("Audi");

        Car car1 = (Car) ctx.getBean("car2");
        car1.setName("BMW");

        System.out.println(car);
        System.out.println(car1);

        /**
         * output: 
         * Car [name=Audi] 
         * Car [name=BMW]
         * */
    }

Bean的生命週期this

    正常狀況下,spring加載bean時,首先會調用構造函數,接着對property賦值時調用setter方法。spa

    若是須要對bean有更多的控制,能夠設置init-method與destroy-method屬性,修改一下car對象,加入init與destory方法:

package cn.net.bysoft.lesson4;

public class Car {

    public Car() {
        System.out.println("1.執行了構造函數。");
    }

    public void init() {
        System.out.println("3.執行初始化。");
    }

    public void destory() {
        System.out.println("5.執行銷燬。");
    }

    @Override
    public String toString() {
        System.out.println("4.使用bean方法。");
        return "Car [name=" + name + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("2.調用setter方法。");
        this.name = name;
    }

    private String name;

}

    在配置文件中爲bean配置init-method與destory-method:

<bean id="car3" class="cn.net.bysoft.lesson4.Car" init-method="init"
    destroy-method="destory" scope="singleton">
    <property name="name" value="Audi"></property>
</bean>

    在進行測試,看看各個方法的執行順序:

@Test
    public void testCycle() {
        Car car = (Car) ctx.getBean("car3");
        System.out.println(car);
        ctx.close();
    }

  1. 執行了構造函數

  2. 執行了setter()方法

  3. 執行了init()方法

  4. 執行了destory()方法

使用bean的後置處理器

    上面的作法是爲單個類進行更多的初始化控制,還能夠配置全局的初始化控制,作法爲,建立一個類使用實現BeanPostProcessor接口,將該類配置到spring配置文件中便可:

package cn.net.bysoft.lesson4;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    // 後置初始化處理
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("after..." + bean.getClass() + ", " + beanName);
        return bean;
    }

    @Override
    // 前置初始化處理
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("before..." + bean.getClass() + ", " + beanName);
        return bean;
    }

}
<bean id="car4" class="cn.net.bysoft.lesson4.Car" init-method="init"
        destroy-method="destory" scope="singleton">
        <property name="name" value="BMW"></property>
    </bean>
    <bean class="cn.net.bysoft.lesson4.MyBeanPostProcessor"></bean>
@Test
    public void testBeanPostProcessor() {
        Car car = (Car) ctx.getBean("car4");
        System.out.println(car);
        ctx.close();
    }


    經過結果能夠看到,配置的處理器before在init方法前被調用,after在init方法後調用。

相關文章
相關標籤/搜索