轉載地址: http://www.cnblogs.com/zrtqsk/p/3735273.html
Spring作爲當前Java最流行、最強大的輕量級框架,準確的瞭解Spring Bean的生命週期非常必要。
通常使用ApplicationContext作爲Spring容器。下面講的也是 ApplicationContext中Bean的生命週期。實際上BeanFactory也是差不多,但是處理器需手動註冊。
一、生命週期流程圖:
Spring Bean的完整生命週期從創建Spring容器開始,直到最終Spring容器銷燬Bean,包含了下面一系列關鍵點,若容器註冊了以下各種接口,那麼程序將會按照下面流程進行:
二、各種接口方法分類
Bean的完整生命週期經歷了各種方法調用,這些方法可以劃分爲以下幾類:
1、Bean自身的方法:這個包括了Bean本身調用的方法和通過配置文件中<bean>的init-method和destroy-method指定的方法;
2、Bean級生命週期接口方法:這個包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這些接口的方法;
3、容器級生命週期接口方法:這個包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 這兩個接口實現,一般稱它們的實現類爲“後處理器”。
4、工廠後處理器接口方法:這個包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工廠後處理器接口的方法。工廠後處理器也是容器級的。在應用上下文裝配配置文件之後立即調用。
三、驗證demo
我們用一個簡單的Spring Bean來演示一下Spring Bean的生命週期。
1、首先是一個簡單的Spring Bean,調用Bean自身的方法和Bean級生命週期接口方法,爲了方便演示,它實現了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這4個接口,同時有2個方法,對應配置文件中<bean>的init-method和destroy-method。如下:
package com.atguigu.test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
/**
* Bean級生命週期接口方法
*/
public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
private String name;
private String address;
private int phone;
private BeanFactory beanFactory;
private String beanName;
public Person() {
System.out.println("【構造器】調用Person的構造器實例化");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("【注入屬性】注入屬性name");
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
System.out.println("【注入屬性】注入屬性address");
this.address = address;
}
public int getPhone() {
return phone;
}
public void setPhone(int phone) {
System.out.println("【注入屬性】注入屬性phone");
this.phone = phone;
}
@Override
public String toString() {
return "Person [address=" + address + ", name=" + name + ", phone=" + phone + "]";
}
// 這是BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out.println("【BeanFactoryAware接口】調用BeanFactoryAware.setBeanFactory()");
this.beanFactory = arg0;
}
// 這是BeanNameAware接口方法
@Override
public void setBeanName(String arg0) {
System.out.println("【BeanNameAware接口】調用BeanNameAware.setBeanName()");
this.beanName = arg0;
}
// 這是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【InitializingBean接口】調用InitializingBean.afterPropertiesSet()");
}
// 這是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("【DiposibleBean接口】調用DiposibleBean.destory()");
}
// 通過<bean>的init-method屬性指定的初始化方法
public void myInit() {
System.out.println("【init-method】調用<bean>的init-method屬性指定的初始化方法");
}
// 通過<bean>的destroy-method屬性指定的初始化方法
public void myDestory() {
System.out.println("【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法");
}
}
2、接下來BeanPostProcessor接口的方法,BeanPostProcessor接口包括2個方法postProcessAfterInitialization和postProcessBeforeInitialization,這兩個方法的第一個參數都是要處理的Bean對象,第二個參數都是Bean的name。返回值是要處理的Bean對象。如下:
package com.atguigu.test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
super();
System.out.println("這是BeanPostProcessor實現類構造器!!");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改!");
return bean;
}
}
3、InstantiationAwareBeanPostProcessor 接口本質是BeanPostProcessor的子接口,一般我們繼承Spring爲其提供的適配器類InstantiationAwareBeanPostProcessorAdapter來使用它,如下:
package com.atguigu.test;
import java.beans.PropertyDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
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 super.postProcessBeforeInstantiation(beanClass, beanName);
}
// 接口方法、實例化Bean之後調用
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor調用postProcessAfterInstantiation方法");
return super.postProcessAfterInstantiation(bean, beanName);
}
// 接口方法、設置某個屬性時調用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法");
return super.postProcessPropertyValues(pvs, pds, bean, beanName);
}
// 接口方法、初始化Bean之前調用
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor調用postProcessBeforeInitialization方法");
return super.postProcessBeforeInitialization(bean, beanName);
}
// 接口方法、初始化Bean之後調用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法");
return super.postProcessAfterInitialization(bean, beanName);
}
}
4、工廠後處理器接口方法,如下:
package com.atguigu.test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("這是BeanFactoryPostProcessor實現類構造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryPostProcessor調用postProcessBeanFactory方法");
BeanDefinition bd = beanFactory.getBeanDefinition("person");
// 此處會調用一次setPhone()方法
bd.getPropertyValues().addPropertyValue("phone", "110");
}
}
5、添加配置類,如下:
package com.atguigu.test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConfigBean {
@Bean(initMethod = "myInit", destroyMethod = "myDestroy")
public Person person() {
Person person = new Person();
person.setAddress("廣州");
person.setName("張三");
person.setPhone("15900000000");
return person;
}
@Bean
public MyBeanFactoryPostProcessor myBeanFactoryPostProcessor() {
return new MyBeanFactoryPostProcessor();
}
@Bean
public MyBeanPostProcessor myBeanPostProcessor() {
return new MyBeanPostProcessor();
}
@Bean
public MyInstantiationAwareBeanPostProcessor myInstantiationAwareBeanPostProcessor() {
return new MyInstantiationAwareBeanPostProcessor();
}
}
6、測試類,關閉容器使用的是實際是AbstractApplicationContext的鉤子方法,如下:
package com.atguigu.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BeanLifeCycle {
public static void main(String[] args) {
System.out.println("現在開始初始化容器");
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigBean.class);
System.out.println("容器初始化成功");
Object person = applicationContext.getBean("person");
System.out.println(person);
System.out.println("現在開始關閉容器!");
((AnnotationConfigApplicationContext) applicationContext).registerShutdownHook();
}
}
7. 測試結果:
// o.s.b.f.s.D == org.springframework.beans.factory.support.DefaultListableBeanFactory
// o.s.c.a.A == org.springframework.context.annotation.AnnotationConfigApplicationContext
// o.s.c.a.C == org.springframework.context.annotation.ConfigurationClassEnhancer
現在開始初始化容器
10:32:18.385 [main] DEBUG o.s.c.a.A - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6842775d
10:32:18.408 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
10:32:18.662 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
10:32:18.665 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'myBeanFactoryPostProcessor'
10:32:18.667 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'configBean'
10:32:18.671 [main] INFO o.s.c.a.C - @Bean method ConfigBean.myBeanFactoryPostProcessor is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
這是BeanFactoryPostProcessor實現類構造器!!
10:32:18.685 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
BeanFactoryPostProcessor調用postProcessBeanFactory方法
10:32:18.687 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
10:32:18.688 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
10:32:18.692 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'myBeanPostProcessor'
這是BeanPostProcessor實現類構造器!!
10:32:18.696 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'myInstantiationAwareBeanPostProcessor'
這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!
10:32:18.702 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'person'
InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法
【構造器】調用Person的構造器實例化
【注入屬性】注入屬性address
【注入屬性】注入屬性name
【注入屬性】注入屬性phone
InstantiationAwareBeanPostProcessor調用postProcessAfterInstantiation方法
InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法
【注入屬性】注入屬性phone // 之所以這裏出現兩次是因爲上面調用了 postProcessPropertyValues 方法
【BeanNameAware接口】調用BeanNameAware.setBeanName()
【BeanFactoryAware接口】調用BeanFactoryAware.setBeanFactory()
BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!
InstantiationAwareBeanPostProcessor調用postProcessBeforeInitialization方法
【InitializingBean接口】調用InitializingBean.afterPropertiesSet()
【init-method】調用<bean>的init-method屬性指定的初始化方法
BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改!
InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法
容器初始化成功
Person [address=廣州, name=張三, phone=110]
現在開始關閉容器!
10:32:18.776 [Thread-0] DEBUG o.s.c.a.A - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6842775d, started on Fri Mar 29 10:32:18 CST 2019
【DiposibleBean接口】調用DiposibleBean.destory()
【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法