上篇文章主要介绍了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初始化前后处理事务。