BeanPostProcessor 是Spring容器中非常重要的概念,基于BeanPostProcessor实现了Spring非常多的特性,这篇文章我我们来阐述BeanPostProcessor 的实现原理和其在Spring容器中的应用实例。顾名思义,BeanPostProcessor 后置处理器,指的是在Bean的生命周期中承担一定的角色,在Bean的不同阶段去执行此处理器。

实现原理

为了更好的说明BeanPostProcessor的执行流程和顺序,这里采用自定义BeanPostProcessor的方法,然后根据方法的调用堆栈来查看执行流程。首先查看一下自定义的 CustomerBeanPostProcessor 。

  1. @Component
  2. public class CustomerBeanPostProcessor implements BeanPostProcessor {
  3. @Override
  4. public Object postProcessBeforeInitialization(Object bean, String beanName)
  5. throws BeansException {
  6. System.out.println("Car.postProcessBeforeInitialization ------ " + beanName);
  7. return bean;
  8. }
  9. @Override
  10. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  11. System.out.println("Car.postProcessAfterInitialization");
  12. return bean;
  13. }
  14. }

我们首先在上面创建的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

    1. // spring-beans-5.1.9.RELEASE-sources.jar!/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java:593
    2. Object exposedObject = bean;
    3. try {
    4. populateBean(beanName, mbd, instanceWrapper);
    5. // 尝试初始化Bean
    6. exposedObject = initializeBean(beanName, exposedObject, mbd);
    7. }
  • 在初始化Bean的过程中,其实现如下,首先调用BeanPostBeforeInitilization方法,然后执行初始化方法,然后在执行BeanPostAfterInitilization方法 ```java // spring-beans-5.1.9.RELEASE-sources.jar!/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java:1768

  1. 而执行 `applyBeanPostProcessorsBeforeInitialization` 方法的代码如下,获取全部的BeanPostProcess,遍历执行,直到返回的值是null,则不再执行
  2. > 执行 applyBeanPostProcessorsAfterInitialization 的方法过程一直,这里不再赘述,读者又兴趣课自行了解
  3. ```java
  4. @Override
  5. public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
  6. throws BeansException {
  7. Object result = existingBean;
  8. for (BeanPostProcessor processor : getBeanPostProcessors()) {
  9. Object current = processor.postProcessBeforeInitialization(result, beanName);
  10. if (current == null) {
  11. return result;
  12. }
  13. result = current;
  14. }
  15. return result;
  16. }

在Spring环境中的应用示例

上文说过BeanPostProcessor 是Spring中非常重要的概念,他是众多Spring特性实现的关键,下面展示了一下基于BeanPostProcessor实现的示例。

InitDestroyAnnotationBeanPostProcessor

在Bean的生命周期的代码中,我们讲解JSR250规范实现的两个注解 @PostConstruct 以及 @PreDestoroy , InitDestroyAnnotationBeanPostProcessor 后置处理器就是实现这两个功能的一个处理器。其实现原理如下:

  1. // 设置init方法和destory类型的方法注解为 `PostConstruct` & `PreDestroy`
  2. setInitAnnotationType(PostConstruct.class);
  3. setDestroyAnnotationType(PreDestroy.class);
  4. private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
  5. // ......
  6. do {
  7. final List<LifecycleElement> currInitMethods = new ArrayList<>();
  8. final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
  9. ReflectionUtils.doWithLocalMethods(targetClass, method -> {
  10. // 寻找初始化方法,也就是方法上标记有 PostConstruct 注解的方法
  11. if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
  12. LifecycleElement element = new LifecycleElement(method);
  13. currInitMethods.add(element);
  14. if (logger.isTraceEnabled()) {
  15. logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
  16. }
  17. }
  18. // 寻找销毁方法,也就是方法上标记有 PreDestroy的方法
  19. if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
  20. currDestroyMethods.add(new LifecycleElement(method));
  21. if (logger.isTraceEnabled()) {
  22. logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
  23. }
  24. }
  25. });
  26. initMethods.addAll(0, currInitMethods);
  27. destroyMethods.addAll(currDestroyMethods);
  28. targetClass = targetClass.getSuperclass();
  29. }
  30. while (targetClass != null && targetClass != Object.class);
  31. return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
  32. new LifecycleMetadata(clazz, initMethods, destroyMethods));
  33. }

在查找方法完成之后,开始执行相应的 BeanPostProcessor 的postProcessBeforeInitialization方法:

  1. @Override
  2. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  3. LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
  4. try {
  5. metadata.invokeInitMethods(bean, beanName);
  6. }
  7. catch (InvocationTargetException ex) {
  8. throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
  9. }
  10. catch (Throwable ex) {
  11. throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
  12. }
  13. return bean;
  14. }
  15. // 开始执行初始化方法,核心代码 element.invoke(target); 这里也再次说明了,Init方法必须是无参的
  16. public void invokeInitMethods(Object target, String beanName) throws Throwable {
  17. Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
  18. Collection<LifecycleElement> initMethodsToIterate =
  19. (checkedInitMethods != null ? checkedInitMethods : this.initMethods);
  20. if (!initMethodsToIterate.isEmpty()) {
  21. for (LifecycleElement element : initMethodsToIterate) {
  22. if (logger.isTraceEnabled()) {
  23. logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
  24. }
  25. element.invoke(target);
  26. }
  27. }
  28. }
  29. @Override
  30. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  31. return bean;
  32. }

而关于PreDestory的实现,则并不是使用PostProcessAfterInitilization方法,而是使用了 DestructionAwareBeanPostProcessor 实现的,此后置处理器会在Bean 销毁的时候调用,这里是后话,记得,BeanPostProcessor 仅仅实现了 PostConstruct 的实现, PreDestory 的实现,则是在`DestructionAwareBeanPostProcessor处理器中实现的。

BeanValidationPostProcessor

在一些应用中,我们需要对创建后的Bean进行校验,以检查Bean是否正确,通常,可以在这里实现此对象的校验,其实现原理如下:

  1. @Override
  2. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  3. if (!this.afterInitialization) {
  4. doValidate(bean);
  5. }
  6. return bean;
  7. }
  8. @Override
  9. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  10. if (this.afterInitialization) {
  11. doValidate(bean);
  12. }
  13. return bean;
  14. }

ApplicationContextAware

在SpringBean的初始化过程,如果需要注入当前上下文,可以使用ApplicationContextAware,其实现原理使用的是,创建后置执行器 ApplicationContextAwareProcessor 执行 postProcessBeforeInitialization 方法, 方法内部判断会否是 ApplicationContextAware 的实例对象,是的话,则执行 invokeAwareInterfaces 方法,该方法中做了多次判断,是否是ApplicationConextAwae,是的强转,将上下文复制

  1. @Override
  2. @Nullable
  3. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  4. if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
  5. bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
  6. bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
  7. return bean;
  8. }
  9. AccessControlContext acc = null;
  10. if (System.getSecurityManager() != null) {
  11. acc = this.applicationContext.getBeanFactory().getAccessControlContext();
  12. }
  13. if (acc != null) {
  14. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  15. invokeAwareInterfaces(bean);
  16. return null;
  17. }, acc);
  18. }
  19. else {
  20. invokeAwareInterfaces(bean);
  21. }
  22. return bean;
  23. }
  24. private void invokeAwareInterfaces(Object bean) {
  25. // 判断其他类型,这里省略
  26. if (bean instanceof ApplicationContextAware) {
  27. ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
  28. }
  29. }