1. 程式人生 > >4.spriing:Bean的生命周期/工廠方法配置Bean/FactoryBean

4.spriing:Bean的生命周期/工廠方法配置Bean/FactoryBean

nts als 函數 new 利用 容器 客戶端 over The

1.Bean的生命周期

scope:singleton/prototype

1)spring容器管理singleton作用的生命周期,spring能夠精確知道Bean合適創建,何時初始化完成,以及何時被銷毀

2)spring容器管理prototype作用的生命周期,spring只負責創建,容器實例化之後就交給客戶端進行管理,spring容器不會再

  跟蹤其生命周期。

可以借鑒servlet的生命周期“實例化--初始化--接受請求--銷毀”

Spring IOC容器可以管理Bean的生命周期,Spring允許在Bean生命周期的特定點執行特定的任務
在SpringIOC容器對Bean的生命周期進行管理的過程
->通過構造器或者工廠的方法創建Bean實例
->為Bean的屬性設置值和其他的Bean的引用
->調用bean的初始化方法
->bea調用使用了
->當容器關閉的時候,調用Bean的銷毀方法
在Bean的聲明裏設置 ini-method

destroy-method屬性,為Bean指定初始化和銷毀的方法

Car.java

public class Car {
    private String brand;public void init() {
        System.out.println("init");
    }public void destroy() {
        System.out.println("destroy");
    }

   public void setBrand(String brand) {
      System.out.println("setBrand");
      this.brand = brand;
    }

  //....
}

applicationContext.xml

<bean id="car" class="com.MrChengs8.TheLifeCycle.Car" init-method="init" 
destroy-method="destroy"> <property name="brand" value="Aodi"></property>
</bean>

測試:

        Car car = (Car) ctx.getBean("car");
        System.out.println(car);
        
        
//關閉IOc容器 //ClassPathXmlApplicationContext //子接口裏面有關閉IOC容器的方法 ctx.close();
setBrand
init Car [brand
=Aodi] destroy

先調用構造函數和設置屬性,然後再init()

Bean的後置處理器:

創建Bean後置處理器:
Bean後置處理器允許在調用初始化的時候對前後的Bean進行額外的處理
Bean的後置處理器對IOC容器裏的所有的Bean實例逐一處理,而非單一的實例,

其典型的應用是:檢查Bean屬性的正確性或者根據特定的標準去修改bean

對Bean後置處理器而言,更需要實現的是Interface BeanPostProcessor接口,在初始化方法被調用的前後,
Spring將把每個Bean的實例分別傳遞給接口以下的兩個方法
->postProcessAfterInitialization(Object arg0, String arg1)
->postProcessBeforeInitialization(Object arg0, String arg1)

實現並提供兩個方法的實現在類中
Object arg0, String arg1
arg0:bean的實例本身
arg1:IOC容器配置的bean的名字
在IOC容器會自動識別是一個後置處理器

TheLatterPostprocessor.java

public class TheLatterPostprocessor implements BeanPostProcessor{

    @Override
    public Object postProcessAfterInitialization(Object bean, String arg1) throws BeansException {
        System.out.println("postProcessAfterInitialization__After__::" + arg1 + "---" + bean);
        Car car = new Car();
        car.setBrand("BBBBB");
        return car;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String arg1) throws BeansException {
        System.out.println("postProcessBeforeInitialization__Before__::" + arg1  + "---" + bean);
        return bean;
    }

}

applicationContext.xml

<!--配置Bean的後置處理器 -->
<bean class="com.MrChengs8.TheLifeCycle.TheLatterPostprocessor"></bean>
setBrand
postProcessBeforeInitialization__Before__::car---Car [brand=Aodi]
init
postProcessAfterInitialization__After__::car---Car [brand=Aodi]
setBrand
Car [brand=BBBBB]
destroy

2.工廠方法配置Bean

1).實例工廠實例化

實例工廠方法:將對象創建的過程封裝到另外一個對象實例方法裏,當客戶需要請求對象時,只需要簡單的調用該實例方法發,不必關心創建的細節
要聲明通過實例工廠方法創建Bean:
->在bean的factory-method屬性裏指定擁有該方法的Bean
->在factory-method屬性裏指定該工廠方法的名稱
->使用 construtor元素為工廠方法傳遞參數

Car.java

public class Car {
    private String brand;
    private double price;public Car(String brand, double price) {
        super();
        this.brand = brand;
        this.price = price;
    }
  //.....    
}

InstanceFactoryMethod.java

public class InstanceFactoryMethod {

    private Map<String, Car> cars = null;
    
    public InstanceFactoryMethod(){
        cars = new HashMap<String, Car>();
        cars.put("aodi", new Car("aodi", 10000));
        cars.put("ford", new Car("ford",20000));
    }
    
    public Car getCar(String name){
        return cars.get(name);
    }
}

applicationContext.xml

<!-- 配置工廠的實例 -->
<bean id="car1" class="com.MrChengs9.FactoryMethod.InstanceFactoryMethod" ></bean>
<!-- 通過實例工廠方法來配置bean -->
<bean id="car2" factory-bean="car1" factory-method="getCar">
    <constructor-arg value="ford"></constructor-arg>
</bean>

測試

        Car car2 = (Car) ctx.getBean("car2");
        System.out.println(car2);
Car [brand=ford, price=20000.0]

2).靜態工廠方法

利用靜態工廠方法可以把bean註入到IOC容器中。在XML文件中配置bean時,要指定class的屬性為工廠的類;factory-method屬性指定工廠類中
工廠方法,用於創建bean;constrctor-arg用於給工廠方法傳遞參數

StaticFactoryMethod.java

public class StaticFactoryMethod {
    private static Map<String, Car> cars = new HashMap<String, Car>();
    
    static{
        cars.put("audi", new Car("audi", 1234));
        cars.put("ford", new Car("ford", 4321));
    }
    
    public static Car getCars(String name){
        return cars.get(name);
    }
}

applicationContext.xml

<!-- 靜態工廠方法來配置Bean實例,不是配置靜態工廠方法實例,而是去配置Bean實例 -->
<!-- 
Class屬性指向靜態工廠方法的全類名
factory-method:指向靜態工廠的名字
constructor-arg:工廠需要傳入canshu,則使用此元素
 -->
<bean id="car" class="com.MrChengs9.FactoryMethod.StaticFactoryMethod" 
factory-method="getCars">
    <constructor-arg value="audi"></constructor-arg>
</bean>
        Car car1 = (Car) ctx.getBean("car");
        System.out.println(car1);
Car [brand=audi, price=1234.0]

3.FactoryBean

FactoryBean是一個接口,要用的話就要實現它。他有三個方法:

  getObject() //返回bean對象

  getObjectType() //返回bean的類型

  isSingleton() //是否單例

CarFactoryBean.java

public class CarFactoryBean implements FactoryBean<Car>{
    
    private String brand;
    public void setBrand(String brand) {
        this.brand = brand;
    }
    //返回bean的對象
    @Override
    public Car getObject() throws Exception {
        // TODO Auto-generated method stub
        return new Car(brand,100000);
    }
    //返回bean的類型
    @Override
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return Car.class;
    }
    //返回bean是不是單實例的
    @Override
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return false;
    }
}

Car.java

public class Car {
    private String brand;
    private double price;public Car(String brand, double price) {
        super();
        this.brand = brand;
        this.price = price;
    }
  //...... }

applicationContext.xml

    通過FactoryBean來配置Bean的實例
    class:指向FactoryBean的全類名
    property:配置FactoryBean的屬性
    但是實際返回的是FactoryBean的getObject()方法
<bean id="car" class="com.MrChengsa.FactoryBean.CarFactoryBean">
    <property name="brand" value="BMW"></property>
</bean>
        Car car = (Car) ctx.getBean("car");
        System.out.println(car);
Car [brand=BMW, price=100000.0]

但實際返回實例確是 FactoryBean 的 getObject() 方法返回的實例!

4.spriing:Bean的生命周期/工廠方法配置Bean/FactoryBean