写文章不易,转载请标明出处。
同时,如果你喜欢我的文章,请关注我,让我们一起进步。
一、概述
这是已经 Spring 源码解析的第四篇博文了,在前面的博文中我们已经通过源码大致分析过了 Spring 当中 Bean 实例化和初始化的流程,并且详细分析了 Spring 当中解决单例 Bean 循环依赖问题的方案,在前面的博文中我们跳过了很多 Spring 实例化和初始化过程中的细节代码,这些代码中很大一部分都是在实例化和初始化 Bean 过程中的生命周期回调方法(官网称为 Lifecycle Callbacks)和一些 *Aware 系列接口(但这两者实现的底层其实都是依赖于 BeanPostProcessor 接口),因此在接下来的系列博文中我们会比较详细的对 Spring 当中的 BeanPostProcessor 进行分析,具体的分析列表大致如下:
(1)ApplicationContextAwareProcessor
(2)InitDestroyAnnotationBeanPostProcessor
(3)InstantiationAwareBeanPostProcessor
(4)CommonAnnotationBeanPostProcessor
(5)AutowiredAnnotationBeanPostProcessor
(6)RequiredAnnotationBeanPostProcessor
(7)BeanValidationPostProcessor
(8)AbstractAutoProxyCreator
二、预备知识
在开始这篇博文的正文之前我们需要先明确一下,到底 Lifecycle Callbacks 和 *Aware 系列接口的功能作用分别是什么,以及它们两个之间又有什么共同点。
2.1 Lifecycle Callbacks
首先,Lifecycle Callbacks 是指生命周期回调方法,这里的生命周期回调方法主要是针对 Bean 来讲(也可以对于整个 Spring 容器的启动和关闭来讲,这里先不考虑),即 Spring 允许外部在 Bean 的初始化和销毁过程中对 Bean 进行一些操作,也可以理解为允许外部在 Bean 生命周期的特定环节通过回调方法来进行一些干预,这些回调的方法一般包括:
(1)实现 InitializingBean 和 DisposeableBean 接口,并实现其回调方法;
(2)配置指定的 init () 和 destroy () 方法(xml 中配置的 init-method 和 destroy-method 以及 Java 注解配置的 @Bean);
(3)为方法添加 @PostConstruct 和 @PreDestroy 注解;
对于它们在初始化时的被调用顺序一般为:
(1)使用 @PostConstruct 注解的方法;
(2)实现 InitializingBean 接口后实现的 afterPropertiesSet () 方法;
(3)配置指定的 init () 方法(通过 xml 配置的 init-method 或者通过 Java 注解配置的 @Bean (init-method = "init") );
销毁时它们被调用的顺序与初始化时相同:
(1)使用 @PreDestroy 注解的方法;
(2)实现 DisposeableBean 接口后实现的 destroy () 方法;
(3)配置指定的 destroy () 方法(通过 xml 配置的 destroy-method 或者通过 Java 注解配置的 @Bean (destroy-method = "destroy" ));
2.2 *Aware 系列接口
对于 *Aware 系列接口,我们先从它的字面意思来分析,aware 即可感知的,意味着实现了这个接口的组件能够感知并获取到自己(或其它组件)的一些属性(组件),具体一点来说,比如我们常用的 BeanNameAware 接口,它的作用就是让 Bean 能够感知到自己的属性,即当我们创建一个 Bean 的时候,它是无法感知到自己在容器中的属性的(它无法获取自己的 BeanName),但是当我们为其实现了 BeanNameAware 接口(接口的定义如下)后,它就可以获取到自己的属性了。
public interface BeanNameAware extends Aware {
void setBeanName(String name);
}
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
正如下面的示例代码,我们可以让 Bean 实现 BeanNameAware 接口,然后实现它的 setBeanName 方法,这样当 Spring 容器在初始化这个 Bean 时发现它实现了 BeanNameAware 接口,就会去调用它的 setBeanName 方法