<bean id="person" class="com.meritit.ysjian.spring3learning.beanlife.Person"
init-method="myInit" destroy-method="myDestory" scope="singleton"
p:id="1001" p:age="125" p:birthday="2013/03/05" />
@上面這個person Bean的作用域是單例singleton,如果scope=”singleton“不顯示指定,也是默認的單例,,如果是通過BeanFactory啓動IoC容器時,BeanFactory#getBean方法在調用時才實例化該Bean,將引用返回調用者,然後在緩存池中緩存該Bean實例,Spring繼續負責其生命週期的管理。 <bean id="person" class="com.meritit.ysjian.spring3learning.beanlife.Person"
init-method="myInit" destroy-method="myDestory" scope="prototype"
p:id="1001" p:age="125" p:birthday="2013/03/05" />
@該Bean的作用域是prototype,容器啓動後,當第一次調用時,Spring容器實例化該Bean並返回給調用者,其後續生命週期由調用者管理,Spring不對其管理,所以prototype作用域destroy-method指定的方法不會執行。在Spring中重要的接口:BeanFactory--->ApplicationContext---->WebApplicationContext,BeanFactory和ApplicationContext在前一篇文章介紹過,
WebApplicationContext wac = (WebApplicationContext) servletContext
.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
WebApplicationContext的初始化在web.xml中進行配置,一種是監聽器,另一種是Servlet自啓動。在前一篇有介紹。public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter {
/**
* 1.調用者通過getBean向容器請求某個Bean時,實例化Bean前進行調用
*/
public Object postProcessBeforeInstantiation(Class beanClass,
String beanName) throws BeansException {
// 1.1僅對容器中的person Bean進行處理
if ("person".equals(beanName)) {
System.out
.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()...");
}
return null;
}
/**
* 2.在實例化Bean後調用,對已經實例化的對象進行"梳妝打扮"
*/
public boolean postProcessAfterInstantiation(Object bean, String beanName)
throws BeansException {
// 2.1進隊容器person Bean進行處理
if ("person".equals(beanName)) {
System.out
.println("MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()...");
}
return true;
}
/**
* 3.postProcessAfterInstantiation方法對Bean進行了處理後調用,
* 將配置值設置到Bean對應的屬性中
*/
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
if ("person".equals(beanName)) {
System.out
.println("MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues()...");
}
return pvs;
}
}
@#postProcessBeforeInstantiation方法在調用者通過getBean向容器請求某個Bean時,實例化Bean前進行調用,進而調用Bean的構造方法實例化對象;@#postProcessAfterInstantiation方法在在實例化Bean後調用,對已經實例化的對象進行"梳妝打扮";
/**
* 自定義Person Bean,實現了Bean級生命接口,管理Bean生命週期的接口
* @author Ysjian
*
*/
public class Person implements BeanFactoryAware, BeanNameAware,
InitializingBean, DisposableBean {
private int id;
private String name;
private int age;
private Date birthday;
public int getId() {
return id;
}
public void setId(int id) {
System.out.println("Person.setId()...");
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
System.out.println("Person.setAge()...");
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("Person.setName()...");
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
System.out.println("Person.setBirthday()...");
this.birthday = birthday;
}
private BeanFactory beanFactory;
private String beanName;
public Person() {
System.out.println("constructor is invoked....");
}
/**
* 1.BeanNameAware接口的方法,
* 在Bean的各項屬性值設置完畢後調用,設置該Bean對應的名稱
*/
public void setBeanName(String beanName) {
System.out.println("Person.setBeanName()....");
this.beanName = beanName;
}
/**
* 2.BeanFactoryAware的接口方法,
* 在該Bean的名稱設置好之後調用,將該Bean的實例設置到容器中
*/
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("Person.setBeanFactory()...");
this.beanFactory = beanFactory;
}
/**
* 3.InitializingBean的接口方法,
* 在後處理器BeanPostProcessor對Bean加工操作以後調用
*/
public void afterPropertiesSet() throws Exception {
System.out.println("Person.afterPropertiesSet()....");
}
/**
* 4.DisposableBean的接口方法,
* singleton單例Bean在容器銷燬後調用的方法
*/
public void destroy() throws Exception {
System.out.println("Person.destroy()...");
}
/**
* 5.通過Bean的init-method指定初始化方法
*/
public void myInit(){
System.out.println("Person.myInit()...");
}
/**
* 6.通過Bean的destroy-method指定初始化方法,
* 單例Bean在DisposableBean#destroy調用後調用,釋放資源等操作
*/
public void myDestory(){
System.out.println("Person.myDestory()...");
}
@Override
public String toString() {
return "Person [birthday=" + birthday + ", id=" + id + ", name=" + name
+ "]";
}
}
@#setBeanName是BeanNameAware接口的方法,在Bean的各項屬性值設置完畢後調用,設置該Bean對應的名稱;@#afterPropertiesSet是InitializingBean的接口方法,在後處理器BeanPostProcessor對Bean加工操作以後調用,所以在這個過程之前有一個Spring級的後處理器BeanPostProcessor做了一次加工;
/**
* Spring級的生命週期接口
* @author Ysjian
*
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
* 該方法可以對Bean進行特殊處理,爲容器提供對Bean進行後續加工處理的切入點,如AOP等
* @param bean 當前的Bean
* @param beanName 當前Bean的配置名
* @return 加工處理後的Bean
*/
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if ("person".equals(beanName)) {
Person person = (Person) bean;
if (person.getAge() > 120) {
System.out
.println("MyBeanPostProcessor.postProcessBeforeInitialization()...");
person.setAge(100);
}
}
return bean;
}
/**
* 2.在init-method屬性指定的方法執行後對Bean再一次進行加工處理
* @param bean 當前的Bean
* @param beanName 當前Bean的配置名
* @return 加工處理後的Bean
*/
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if ("person".equals(beanName)) {
Person person = (Person) bean;
if (person.getName() == null) {
System.out
.println("MyBeanPostProcessor.postProcessAfterInitialization()...");
person.setName("ysjian");
}
}
return bean;
}
}
@詳細說明,代碼中註釋了;public class BeanLifeCycle {
public static void main(String[] args) {
LifeCycleBeanFactory();
}
private static void LifeCycleBeanFactory() {
Resource resource = new ClassPathResource("beans.xml");
BeanFactory bf = new XmlBeanFactory(resource);
ConfigurableBeanFactory cFactory = (ConfigurableBeanFactory) bf;
// 向容器註冊MyBeanPostProcessor
cFactory.addBeanPostProcessor(new MyBeanPostProcessor());
// 向容器註冊MyInstantiationAwareBeanPostProcessor
cFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
Person person1 = bf.getBean("person", Person.class);
// 如果bean的scope="singleton",Spring容器繼續負責bean的生命週週期,放入緩存池中,爲true,否則否則交給用戶,結果爲false,
person1.setName("first ysjian");
Person person2 = bf.getBean("person", Person.class);
System.out.println("person1 == person2:" + (person1 == person2));
// 關閉容器
((XmlBeanFactory) bf).destroySingletons();
}
}
@ConfigurableBeanFactory#addBeanPostProcessor是用來註冊我們自定義的後處理器的,這樣註冊後,才生效。@來看看我們的Bean的生命演化結果:
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()...
constructor is invoked....
MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()...
MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues()...
Person.setAge()...
Person.setBirthday()...
Person.setId()...
Person.setBeanName()....
Person.setBeanFactory()...
MyBeanPostProcessor.postProcessBeforeInitialization()...
Person.setAge()...
Person.afterPropertiesSet()....
Person.myInit()...
MyBeanPostProcessor.postProcessAfterInitialization()...
Person.setName()...
Person.setName()...
person1 == person2:true
Person.destroy()...
Person.myDestory()...
3.ApplicationContext中Bean的初始化經歷了一系列過程:
/**
* 自定義工廠後處理器
* @author Ysjian
*
*/
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
/**
* 在getBean之前對配置文件中配置的Bean的信息進行個性化更改
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf)
throws BeansException {
BeanDefinition bd = bf.getBeanDefinition("car");
//更改配置文件的配置信息
bd.getPropertyValues().addPropertyValue("brand", "BMW");
System.out
.println("MyBeanFactoryPostProcessor.postProcessBeanFactory()");
}
}
@這個自定義的工廠後處理器就是在getBean之前對配置文件的信息進行個性化更改beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="person" class="com.meritit.ysjian.spring3learning.beanlife.Person"
init-method="myInit" destroy-method="myDestory" scope="singleton"
p:id="1001" p:age="125" p:birthday="2013/03/05" />
<bean id="myBeanPostProcessor"
class="com.meritit.ysjian.spring3learning.beanfactory.MyBeanPostProcessor" />
<bean id="myBeanFactoryPostProcessor"
class="com.meritit.ysjian.spring3learning.context.MyBeanFactoryPostProcessor" />
<bean id="myInstantiationAwareBeanPostProcessor"
class="com.meritit.ysjian.spring3learning.beanfactory.MyInstantiationAwareBeanPostProcessor" />
</beans>
@ApplicationContext只需要在配置文件中定義自定義的後處理器,讓後容器啓動的時候回自動識別,讓後自動註冊;private static void LifeCycleApplicationContext() {
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
Person person1 = ac.getBean("person", Person.class);
// 如果bean的scope="singleton",Spring容器繼續負責bean的生命週週期,放入緩存池中,爲true,否則否則交給用戶,結果爲false,
// person1.setName("first ysjian");
Person person2 = ac.getBean("person", Person.class);
System.out.println("person1 == person2:" + (person1 == person2));
System.out.println(person1.getName()+"--------------");
}
@結果是:ysjian003--------------,就是說我們自定義的工廠後處理器在getBean調用之前將配置文件中沒有的name屬性設置爲ysjian003了,但不常用。