4.spriing:Bean的生命週期/工廠方法配置Bean/FactoryBean
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
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() 方法返回的例項!