上篇文章主要介绍了Bean生命周期,bean生命周期:创建bean--->初始化init--->销毁destory,而初始化和销毁是可以用@Bean指定的,或者用@PostCoustruct@preDestory注解,或者用InitializingBean和DisposableBean接口都能指定调用的初始化和销毁方法:
Bean生命周期(2)---Spring源码从入门到精通(八)
这篇主要介绍BeanPostProcessor,在spring框架非常重要,里面有两个接口,一个是postProcessBeforeInitialization 和 postProcessAfterInitialization两个方法,顾名思义,前者在类初始化前调用,后者在类初始化之后调用。
下面主要分为三个部分:
1、BeanPostProcessor实用。
2、BeanPostProcessor源码解析。
3、Spring底层使用BeanPostProcessor。
1、BeanPostProcessor实用
先自定义类MyBeanPostProcessor实现接口,会重写里面的两个方法,可以打印出当前初始化的类。
/**
* 自定义类实现beanPostProcessor接口,两个重写的方法在bean初始化前后调用。
*
* 初始化之前用populateBean()方法,给bean属性赋值
* 初始化开始:
* 「
* applyBeanPostProcessorsBeforeInitialization()初始化之前调用的方法 , 接口BeanPostProcessor
* invokeInitMethods()方法初始化 ,执行bean初始化
* applyBeanPostProcessorsAfterInitialization()初始化之后调用的方法 , 接口BeanPostProcessor
* 」
*
* @author keying
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(
"postProcessBeforeInitialization.....Before..." + bean.getClass() + ",【beanName】=" + beanName);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(
"postProcessAfterInitialization.....After..." + bean.getClass() + ",【beanName】=" + beanName);
return bean;
}
}
junitTest还和上篇文章一样不变,直接运行,为了方便理解,再贴一遍:
@Test
public void test() {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
ConfigLifeCycle.class);
System.out.println("容器创建完毕");
//多实例情况下,需要获取组件,才会初始化,并且不会销毁
//Object carObject = annotationConfigApplicationContext.getBean("car");
//getDefinitionNames(annotationConfigApplicationContext);
annotationConfigApplicationContext.close();
}
控制台打印如下,我们创建的三个bean在初始化的前后都会打印:
2、BeanPostProcessor源码解析。
1、刚开始AnnotationConfigApplicationContext主要调用refresh()方法
2、点进去之后,refresh主要调用finishBeanFactoryInitialization方法,初始化所有单实例对象 3、点进去之后,调用下图的beanFactory.preInstantiateSingletons方法
4、初始化单实例 bean之后,点进去此方法,可以看到getBean方法5、点进getBean之后,可以看到下图方法,获取单实例,若获取不到,就会createBean创建对象并且返回。6、createBean里有个doCreateBean,点进此方法,里面有个populateBean方法作用是在初始化对象之前,给bean注入信息,bean名,工厂名,之后下面的initializeBean方法,后面的方法就是处理器的调用。
7、点进initializaBean方法可以看到,里面有三个方法,中间invokeInitMethods方法就是初始化bean,applyBeanPostProcessorsBeforeInitialization方法为初始化之前调用的,applyBeanPostProcessorsAfterInitialization方法为初始化之后调用的。8、点击applyBeanPostProcessorsBeforeInitialization方法,进入可以看到,遍历获取容器所有的beanPostProcessors,挨个执行beforeInitialization若返回为 null,则跳出for循环,不会执行后面的postBeforeBeforeInitialization方法。
3、Spring底层使用BeanPostProcessor
可以传递ApplicationContext对象,用bean实现ApplicationContextAware方法,代码如下:
@Component
public class Cat implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Cat(){
System.out.println("Cat...construct");
}
/**
* construct 构造函数创建对象之后执行
*/
@PostConstruct
public void init(){
System.out.println("cat ...PostConstruct.");
}
/**
* 销毁之前调用
*/
@PreDestroy
public void destory(){
System.out.println("cat ...PreDestroy");
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
源码如下,ApplicationContextAwareProcessor类就是集成了此接口,里面可以设置代码里的ApplicationContext。
BeanValidationPostProcessor类,作用在bean初始化前后进行效验,源码如下。
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!this.afterInitialization) {
this.doValidate(bean);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (this.afterInitialization) {
this.doValidate(bean);
}
return bean;
}
之前用的@PostConstruct,和@PreDestroy注解也是因为BeanPostProcessor才运行的,在InitDestroyAnnotationBeanPostProcessor类里,调用invokeInitMethods方法点进invokeInitmethods方法可以看到,会用反射调用element.invoke方法,找到对应的bean。
还有AutowiredAnnotationBeanPostProcessor类,就是在对象创建完之后,处理@Autowired注解获取到bean对象。
所有@Bean注入对象,其他方法注入组件,@Autowired,生命周期注解,@Async异步注解等等,都是基本BeanPostProcessor接口实现的。
简单总结:spring生命周期,主要为bean创建--->init初始化--->销毁,
单实例在容器加载完毕前,创建和初始化,多实例在获取bean的时候才会创建bean和初始化。@Bean注释可以指定init-method和destory-method来初始化和销毁,@PostConstruct注解和接口也可以实现,这些都基于BeanPostRrocessor接口,控制生命周期,并且实现此接口,可以在bean初始化前后处理事务。