Spring中Bean的生命周期
Bean的生命周期
解釋
(1)BeanFactoryPostProcessor的postProcessorBeanFactory()方法:若某個IoC容器內添加了實現了BeanFactoryPostProcessor接口的實現類Bean,那么在該容器中實例化任何其他Bean之前可以回調該Bean中的postPrcessorBeanFactory()方法來對Bean的配置元數據進行更改,比如從XML配置文件中獲取到的配置信息。
(2)Bean的實例化:Bean的實例化是使用反射實現的。
(3)Bean屬性注入:Bean實例化完成后,利用反射技術實現屬性及依賴Bean的注入。
(4)BeanNameAware的setBeanName()方法:如果某個Bean實現了BeanNameAware接口,那么Spring將會將Bean實例的ID傳遞給setBeanName()方法,在Bean類中新增一個beanName字段,並實現setBeanName()方法。
(5)BeanFactoryAware的setBeanFactory()方法:如果某個Bean實現了BeanFactoryAware接口,那么Spring將會將創建Bean的BeanFactory傳遞給setBeanFactory()方法,在Bean類中新增了一個beanFactory字段用來保存BeanFactory的值,並實現setBeanFactory()方法。
(6)ApplicationContextAware的setApplicationContext()方法:如果某個Bean實現了ApplicationContextAware接口,那么Spring將會將該Bean所在的上下文環境ApplicationContext傳遞給setApplicationContext()方法,在Bean類中新增一個ApplicationContext字段用來保存ApplicationContext的值,並實現setApplicationContext()方法。
(7)BeanPostProcessor預初始化方法:如果某個IoC容器中增加的實現BeanPostProcessor接口的實現類Bean,那么在該容器中實例化Bean之后,執行初始化之前會調用BeanPostProcessor中的postProcessBeforeInitialization()方法執行預初始化處理。
(8)InitializingBean的afterPropertiesSet()方法:如果Bean實現了InitializingBean接口,那么Bean在實例化完成后將會執行接口中的afterPropertiesSet()方法來進行初始化。
(9)自定義的inti-method指定的方法:如果配置文件中使用init-method屬性指定了初始化方法,那么Bean在實例化完成后將會調用該屬性指定的初始化方法進行Bean的初始化。
(10)BeanPostProcessor初始化后方法:如果某個IoC容器中增加的實現BeanPostProcessor接口的實現類Bean,那么在該容器中實例化Bean之后並且完成初始化調用后執行該接口中的postProcessorAfterInitialization()方法進行初始化后處理。
(11)使用Bean:此時有關Bean的所有准備工作均已完成,Bean可以被程序使用了,它們將會一直駐留在應用上下文中,直到該上下文環境被銷毀。
(12)DisposableBean的destory()方法:如果Bean實現了DisposableBean接口,Spring將會在Bean實例銷毀之前調用該接口的destory()方法,來完成一些銷毀之前的處理工作。
(13)自定義的destory-method指定的方法:如果在配置文件中使用destory-method指定了銷毀方法,那么在Bean實例銷毀之前會調用該指定的方法完成一些銷毀之前的處理工作。
注意:
1、BeanFactoryPostProcessor接口與BeanPostProcessor接口的作用范圍是整個上下文環境中,使用方法是單獨新增一個類來實現這些接口,那么在處理其他Bean的某些時刻就會回調響應的接口中的方法。
2、BeanNameAware、BeanFactoryAware、ApplicationContextAware的作用范圍的Bean范圍,即僅僅對實現了該接口的指定Bean有效,所有其使用方法是在要使用該功能的Bean自己來實現該接口。
3、第8點與第9點所述的兩個初始化方法作用是一樣的,我們完全可以使用其中的一種即可,一般情況我們使用第9點所述的方式,盡量少的去來Bean中實現某些接口,保持其獨立性,低耦合性,盡量不要與Spring代碼耦合在一起。第12和第13也是如此。
4、 在BeaFactoryAware's setBeanFactory()和Pre-initialization BeanPostProcessor之間還應該有一步:調用ApplicationContextAware的setApplicationContext()方法。
可以看到Bean生命周期要經歷很多階段,但這些階段大部分都是可選的。例如,某個Bean如果實現了BeanFactoryAware接口的setBeanFactory方法,那么該Bean的生命就會經歷這個階段,如果不實現則沒有。
使用
public class Book implements BeanNameAware, BeanFactoryAware,
ApplicationContextAware, InitializingBean, DisposableBean {
private String bookName;
public Book(){
System.out.println("Book Initializing ");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("Book.setBeanFactory invoke");
}
@Override
public void setBeanName(String name) {
System.out.println("Book.setBeanName invoke");
}
@Override
public void destroy() throws Exception {
System.out.println("Book.destory invoke");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Book.afterPropertiesSet invoke");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("Book.setApplicationContext invoke");
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
System.out.println("setBookName: Book name has set.");
}
public void myPostConstruct(){
System.out.println("Book.myPostConstruct invoke");
}
// 自定義初始化方法
@PostConstruct
public void springPostConstruct(){
System.out.println("@PostConstruct");
}
public void myPreDestory(){
System.out.println("Book.myPreDestory invoke");
System.out.println("---------------destroy-----------------");
}
// 自定義銷毀方法
@PreDestroy
public void springPreDestory(){
System.out.println("@PreDestory");
}
@Override
protected void finalize() throws Throwable {
System.out.println("------inside finalize-----");
}
}
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("這是BeanFactoryPostProcessor實現類構造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
throws BeansException {
System.out
.println("BeanFactoryPostProcessor調用postProcessBeanFactory方法");
BeanDefinition bd = arg0.getBeanDefinition("book");
bd.getPropertyValues().addPropertyValue("bookName", "ddd");
}
}
// 通過注入調用
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof Book){
System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof Book){
System.out.println("MyBeanPostProcessor.postProcessAfterInitialization");
}
return bean;
}
}
// ClassPathXmlApplicationContext 這個類實例化就會調用這個類
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("這是BeanFactoryPostProcessor實現類構造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
throws BeansException {
System.out
.println("BeanFactoryPostProcessor調用postProcessBeanFactory方法");
BeanDefinition bd = arg0.getBeanDefinition("book");
bd.getPropertyValues().addPropertyValue("bookName", "ddd");
}
}
// InstantiationAwareBeanPostProcessor 接口本質是BeanPostProcessor的子接口,一般我們繼承Spring為其提供的適配器類InstantiationAwareBeanPostProcessor Adapter來使用它,如下:
public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter {
public MyInstantiationAwareBeanPostProcessor() {
super();
System.out
.println("這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!");
}
// 接口方法、實例化Bean之前調用
@Override
public Object postProcessBeforeInstantiation(Class beanClass,
String beanName) throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法");
return null;
}
// 接口方法、實例化Bean之后調用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法");
return bean;
}
// 接口方法、設置某個屬性時調用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法");
return pvs;
}
}
// bean配置
<?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: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.2.xsd">
<bean id="beanPostProcessor" class="com.example.demo.MyBeanPostProcessor">
</bean>
<bean id="instantiationAwareBeanPostProcessor" class="com.example.demo.MyInstantiationAwareBeanPostProcessor">
</bean>
<bean id="beanFactoryPostProcessor" class="com.example.demo.MyBeanFactoryPostProcessor">
</bean>
<bean id="book" class="com.example.demo.Book" init-method="myPostConstruct" destroy-method="myPreDestory">
<!-- 注入bean 屬性名稱 -->
<property name="bookName" value="thingking in java" />
</bean>
</beans>
//調用
ApplicationContext context = new ClassPathXmlApplicationContext("beanconfig.xml");
Book book = (Book)context.getBean("book");
System.out.println("Book name = " + book.getBookName());
((ClassPathXmlApplicationContext) context).destroy();