BeanPostProcessor 是Spring容器中非常重要的概念,基于BeanPostProcessor实现了Spring非常多的特性,这篇文章我我们来阐述BeanPostProcessor 的实现原理和其在Spring容器中的应用实例。顾名思义,BeanPostProcessor 后置处理器,指的是在Bean的生命周期中承担一定的角色,在Bean的不同阶段去执行此处理器。
实现原理
为了更好的说明BeanPostProcessor的执行流程和顺序,这里采用自定义BeanPostProcessor的方法,然后根据方法的调用堆栈来查看执行流程。首先查看一下自定义的 CustomerBeanPostProcessor 。
@Componentpublic class CustomerBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {System.out.println("Car.postProcessBeforeInitialization ------ " + beanName);return bean;}@Overridepublic 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:593Object exposedObject = bean;try {populateBean(beanName, mbd, instanceWrapper);// 尝试初始化BeanexposedObject = 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@Overridepublic 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方法:
@Overridepublic 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);}}}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
而关于PreDestory的实现,则并不是使用PostProcessAfterInitilization方法,而是使用了 DestructionAwareBeanPostProcessor 实现的,此后置处理器会在Bean 销毁的时候调用,这里是后话,记得,BeanPostProcessor 仅仅实现了 PostConstruct 的实现, PreDestory 的实现,则是在`DestructionAwareBeanPostProcessor处理器中实现的。
BeanValidationPostProcessor
在一些应用中,我们需要对创建后的Bean进行校验,以检查Bean是否正确,通常,可以在这里实现此对象的校验,其实现原理如下:
@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (!this.afterInitialization) {doValidate(bean);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (this.afterInitialization) {doValidate(bean);}return bean;}
ApplicationContextAware
在SpringBean的初始化过程,如果需要注入当前上下文,可以使用ApplicationContextAware,其实现原理使用的是,创建后置执行器 ApplicationContextAwareProcessor 执行 postProcessBeforeInitialization 方法, 方法内部判断会否是 ApplicationContextAware 的实例对象,是的话,则执行 invokeAwareInterfaces 方法,该方法中做了多次判断,是否是ApplicationConextAwae,是的强转,将上下文复制
@Override@Nullablepublic 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);}}
