BeanPostProcessor 是Spring容器中非常重要的概念,基于BeanPostProcessor实现了Spring非常多的特性,这篇文章我我们来阐述BeanPostProcessor 的实现原理和其在Spring容器中的应用实例。顾名思义,BeanPostProcessor 后置处理器,指的是在Bean的生命周期中承担一定的角色,在Bean的不同阶段去执行此处理器。
实现原理
为了更好的说明BeanPostProcessor的执行流程和顺序,这里采用自定义BeanPostProcessor的方法,然后根据方法的调用堆栈来查看执行流程。首先查看一下自定义的 CustomerBeanPostProcessor 。
@Component
public class CustomerBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("Car.postProcessBeforeInitialization ------ " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Car.postProcessAfterInitialization");
return bean;
}
}
我们首先在上面创建的CustomerBeanPostProcessor的类的postProcessBeforeInitialization
方法上添加断点,启动Spring应用,可以看到,程序进入断点,查看调用的方法栈。
- 首先Spring在启动的时候,刷新上下文,调用方法
finishBeanFactoryInitialization(beanFactory);
(位于 /spring-context-5.1.9.RELEASE-sources.jar!/org/springframework/context/support/AbstractApplicationContext.java:849) - 在该方法中中,尝试调用方法
beanFactory.preInstantiateSingletons();
进行准备单例实例 后续是根据BeanDefinition来不断的创建Bean实例,创建Bean实例完成之后,尝试设置属性以及初始化Bean
// spring-beans-5.1.9.RELEASE-sources.jar!/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java:593
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
// 尝试初始化Bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
在初始化Bean的过程中,其实现如下,首先调用BeanPostBeforeInitilization方法,然后执行初始化方法,然后在执行BeanPostAfterInitilization方法 ```java // spring-beans-5.1.9.RELEASE-sources.jar!/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java:1768
而执行 `applyBeanPostProcessorsBeforeInitialization` 方法的代码如下,获取全部的BeanPostProcess,遍历执行,直到返回的值是null,则不再执行
> 执行 applyBeanPostProcessorsAfterInitialization 的方法过程一直,这里不再赘述,读者又兴趣课自行了解
```java
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
在Spring环境中的应用示例
上文说过BeanPostProcessor 是Spring中非常重要的概念,他是众多Spring特性实现的关键,下面展示了一下基于BeanPostProcessor实现的示例。
InitDestroyAnnotationBeanPostProcessor
在Bean的生命周期的代码中,我们讲解JSR250规范实现的两个注解 @PostConstruct
以及 @PreDestoroy
, InitDestroyAnnotationBeanPostProcessor 后置处理器就是实现这两个功能的一个处理器。其实现原理如下:
// 设置init方法和destory类型的方法注解为 `PostConstruct` & `PreDestroy`
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
// ......
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 寻找初始化方法,也就是方法上标记有 PostConstruct 注解的方法
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
// 寻找销毁方法,也就是方法上标记有 PreDestroy的方法
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (logger.isTraceEnabled()) {
logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
在查找方法完成之后,开始执行相应的 BeanPostProcessor 的postProcessBeforeInitialization方法:
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
// 开始执行初始化方法,核心代码 element.invoke(target); 这里也再次说明了,Init方法必须是无参的
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
Collection<LifecycleElement> initMethodsToIterate =
(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
if (!initMethodsToIterate.isEmpty()) {
for (LifecycleElement element : initMethodsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
element.invoke(target);
}
}
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
而关于PreDestory的实现,则并不是使用PostProcessAfterInitilization方法,而是使用了 DestructionAwareBeanPostProcessor
实现的,此后置处理器会在Bean 销毁的时候调用,这里是后话,记得,BeanPostProcessor 仅仅实现了 PostConstruct
的实现, PreDestory
的实现,则是在`DestructionAwareBeanPostProcessor
处理器中实现的。
BeanValidationPostProcessor
在一些应用中,我们需要对创建后的Bean进行校验,以检查Bean是否正确,通常,可以在这里实现此对象的校验,其实现原理如下:
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!this.afterInitialization) {
doValidate(bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (this.afterInitialization) {
doValidate(bean);
}
return bean;
}
ApplicationContextAware
在SpringBean的初始化过程,如果需要注入当前上下文,可以使用ApplicationContextAware,其实现原理使用的是,创建后置执行器 ApplicationContextAwareProcessor
执行 postProcessBeforeInitialization
方法, 方法内部判断会否是 ApplicationContextAware
的实例对象,是的话,则执行 invokeAwareInterfaces
方法,该方法中做了多次判断,是否是ApplicationConextAwae,是的强转,将上下文复制
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
// 判断其他类型,这里省略
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}