Spring中的BeanPostProcessor详解

 Spring中的BeanPostProcessor详解

概述

  • BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初始化前后)会回调BeanPostProcessor中定义的两个方法。BeanPostProcessor的源码如下
public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
  • 其中postProcessBeforeInitialization方法会在每一个bean对象的初始化方法调用之前回调;postProcessAfterInitialization方法会在每个bean对象的初始化方法调用之后被回调。

执行原理

  • BeanPostProcessor的执行是定义在容器的刷新过程中,容器刷新对象具体的方法为:AbstractApplicationContext.refresh()。在refresh方法执行的调用栈中会去调用AbstractAutowireCapableBeanFactory.doCreateBean()方法,该方法节选源码如下
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    
    invokeInitMethods(beanName, wrappedBean, mbd);

    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}
  • 看到在调用初始化方法前后会分别调用applyBeanPostProcessorsBeforeInitialization()和applyBeanPostProcessorsAfterInitialization()。applyBeanPostProcessorsBeforeInitialization()方法的源码如下
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    //获取所有的BeanPostProcessor进行遍历
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        result = beanProcessor.postProcessBeforeInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}
  • 可以看到其逻辑为遍历得到容器中所有的BeanPostProcessor,然后一次执行postProcessBeforeInitialization,一但返回null,就跳出for循环不执行后面的BeanPostProcessor.postProcessorsBeforeInitialization()。也就是说如果返回的是null那么我们通过getBean方法将得不到目标Bean。
  • applyBeanPostProcessorsBeforeInitialization()方法的逻辑和上面一致,就是将循环执行的beanProcessor.postProcessBeforeInitialization()替换成beanProcessor.postProcessAfterInitialization()Spring底层的很多功能特性都是借助BeanPostProcessor的子类来实现。

常见BeanPostProcessor分析

  • 下图是debug过程中,ApplicationContext对象中的包含的BeanPostProcessor。具体包含哪些BeanPostProcessor和具体应用程序相关,除了下标3中的MyBeanPostProcessor为自定义的BeanPostProcessor,其余均为Spring自带的BeanPostProcessor。

  • 1159210-20190902205639263-148933033.png
  • ApplicationContextAwareProcessor
    • ApplicationContextAwareProcessor后置处理器的作用是,当应用程序定义的Bean实现ApplicationContextAware接口时注入ApplicationContext对象。
    @Component
    public class Car implements ApplicationContextAware {
    
        private ApplicationContext applicationContext;
    
        public Car(){
            System.out.println("car instance...");
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            System.out.println("ApplicationContextAware...setApplicationContext()");
            this.applicationContext = applicationContext;
        }
    }
    • 那Car是如何通过实现ApplicationContextAware接口就能获得ApplicationContext对象呢?答案是通过ApplicationContextAwareProcessor后置处理器来实现,我们来看看ApplicationContextAwareProcessor的源码
    class ApplicationContextAwareProcessor implements BeanPostProcessor {
    
      private final ConfigurableApplicationContext applicationContext;
    
      private final StringValueResolver embeddedValueResolver;
    
    
      /**
       * Create a new ApplicationContextAwareProcessor for the given context.
       */
      public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
          this.applicationContext = applicationContext;
          this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
      }
    
    
      @Override
      public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
          AccessControlContext acc = null;
          // 这里bean是Car,它实现了ApplicationContextAware接口
          if (System.getSecurityManager() != null &&
                  (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                          bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                          bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
              invokeAwareInterfaces(bean);
          }
    
          return bean;
      }
    
      private void invokeAwareInterfaces(Object bean) {
          if (bean instanceof Aware) {
              if (bean instanceof EnvironmentAware) {
                  ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
              }
              if (bean instanceof EmbeddedValueResolverAware) {
                  ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
              }
              if (bean instanceof ResourceLoaderAware) {
                  ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
              }
              if (bean instanceof ApplicationEventPublisherAware) {
                  ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
              }
              if (bean instanceof MessageSourceAware) {
                  ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
              }
              if (bean instanceof ApplicationContextAware) {
                  // 会执行这里回调car重写的setApplicationContext方法,然后将this.applicationContext注入给Car
                  ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
              }
          }
      }
    
      @Override
      public Object postProcessAfterInitialization(Object bean, String beanName) {
          return bean;
      }
    
    }
  • InitDestroyAnnotationBeanPostProcessor
    • InitDestroyAnnotationBeanPostProcessor后置处理器是用来处理自定义的初始化方法和销毁方法。
    • Spring中提供了3种自定义初始化和销毁方法:1.通过@Bean指定init-method和destroy-method属性;2.Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑); 3.@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法@PreDestroy:在容器销毁bean之前通知我们进行清理工作
    • InitDestroyAnnotationBeanPostProcessor的作用就是让第3种方式生效。先看看如何使用@PostConstruct和@PreDestroy注解。
    @Component
    public class Car {
    
        public Car(){
            System.out.println("car instance...");
        }
    
        /**
         * 自定义的初始化方法
         */
        @PostConstruct
        public void init(){
            System.out.println("car ... init...");
        }
    
        /**
         * 自定义的销毁方法
         */
        @PreDestroy
        public void detory(){
            System.out.println("car ... detory...");
        }
    }
    • InitDestroyAnnotationBeanPostProcessor会在Bean创建的时候通过反射的方式查找包含@PostConstruct和@PreDestroy注解的方法,然后再通过反射执行方法。我们来看看InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()的源码

使用

  • 我们定义一个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进行处理。
public class ConfigValueBeanProcessor implements BeanPostProcessor ,Ordered {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        ReflectionUtils.doWithLocalFields(bean.getClass(), (field -> {
            System.out.println(field.toString());
            Value valueAnnotation = field.getAnnotation(Value.class);
            if (valueAnnotation != null) {
                if (Modifier.isStatic(field.getModifiers())) {
                    return;
                }

            }
        }));
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}

//配置类中定义bean
  @Bean
  public ConfigValueBeanProcessor getConfigValueBeanProcessor() {
      return new ConfigValueBeanProcessor();
  }

转载于:https://www.cnblogs.com/frankltf/p/11449033.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值