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。

  • 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();
}

最新文章

  1. 关于Array的map方法中回调函数参数的问题
  2. 163邮件出错:不允许使用邮箱名称。 服务器响应为: authentication is required,smtp7,C8CowEDpS0+Uke9VvSmXBg--.546S2 1441763733
  3. scrapy爬虫结果插入mysql数据库
  4. NSDate 时间
  5. C++ 隐式类类型转换
  6. flask 项目的开发经验总结
  7. JVM的栈内存
  8. Singleton(单例模式)
  9. Android牛博
  10. java单链表代码实现
  11. ioctl函数详细说明
  12. windows下nginx的安装及使用方法入门
  13. 常用oralce_sql
  14. Android 环境搭建、基础窗口window/Mac
  15. C#学习笔记-工厂模式
  16. Environment.getExternalStorageDirectory()
  17. 行为驱动:Cucumber + Selenium + Java(五) - 使用maven来实现cucumber测试和报告
  18. 第九节: 利用RemoteScheduler实现Sheduler的远程控制
  19. 配置notepad++支持golang开发
  20. CRF 条件随机场工具包

热门文章

  1. KAFKA报错:COMMIT CANNOT BE COMPLETED SINCE THE GROUP HAS ALREADY REBALANCED AND ASSIGNED THE PARTITIONS TO ANOTHER MEMBER
  2. vc调用mysql数据库操作例子
  3. IDEA到期了?不用怕,最新的永久激活送给你
  4. 洛谷P4141 消失之物 题解 背包问题扩展
  5. 更换EMC VNX系列存储故障硬盘的检查步骤
  6. javascript-void keyword
  7. AtomicXXX系列类使用分析
  8. OpenJ_Bailian 4103 踩方格(搜索 动态规划 )
  9. Go Web 编程之 请求
  10. Java控制台五子棋(纯算法)