前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring学习(三)后置处理器BeanPostProcessor

Spring学习(三)后置处理器BeanPostProcessor

作者头像
虞大大
发布2020-08-26 17:20:43
3790
发布2020-08-26 17:20:43
举报
文章被收录于专栏:码云大作战码云大作战

一、后置处理器简单示例

(1)申明一个TestService类,并加上@Component注解,由Spring在启动时加载TestService的bean。

代码语言:javascript
复制
@Component
public class TestService {
    
    private String name;
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

(2)申明一个测试类,并实现BeanPostProcessor作为后置处理器,对TestSerivce的bean进行后置处理。

代码语言:javascript
复制
@Component
public class TestOfBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        if (bean instanceof TestService) {
            TestService testService = (TestService) bean;
            testService.setName("postProcessBeforeInitialization处理器");
            System.out.println("testService postProcessBeforeInitialization处理器");
        }

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof TestService) {
            TestService testService = (TestService) bean;
            testService.setName("postProcessAfterInitialization处理器");
            System.out.println("testService postProcessAfterInitialization处理器");
        }
        return bean;
    }
}

(3)启动容器。

代码语言:javascript
复制
public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    TestService testServiceBean = context.getBean(TestService.class);
    System.out.println(testServiceBean.getName());
}

(4)观察打印结果。

先执行后置处理器中的postProcessBeforeInitialization方法,后执行后置处理器中的postProcessAfterInitialization方法。并且在后置处理器中name属性被设置了值。

二、spring加载时后置处理器被调用了多少次

· org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

第一次调用后置处理器是在创建bean早期对象之前,判断该bean是否存在aop,如果存在aop,即bean!=null会通过后置处理器,将bean作为代理对象返回。

· org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors

第二次调用后置处理器也是在创建bean早期对象之前,不过可以看出这里的代码是和构造函数相关,这里就是用来推断创建bean早期对象的构造方法。

· org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors

第三次调用后置处理器是在bean的早期对象被创建后执行(即只是创建完构造函数)。在这里会对bean中的注解进行解析进行属性合并。

例如:

@PostConstruct、@Resource注解是使用CommonAnnotationBeanPostProcessor处理器。

@Autowired、@Value注解是使用AutowiredAnnotationBeanPostProcessor处理器。

· org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference

第四次调用后置处理器是在将bean工厂加入到二级缓存时期被执行,主要作用是为了在bean还没有完全被创建出来前,暴露bean的早期引用。将bean工厂加入到二级缓存主要是为了解决循环依赖,前面的bean初始化过程中已作出解释。

· org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(一)

代码语言:javascript
复制
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
代码语言:javascript
复制
   //...
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
}//...}

第五次调用后置处理器是在对bean进行属性依赖注入时执行。这里会判断是否需要进行后续的属性注入,如果返回false,那么循环就会break,并且在后续代码中就会被return出去,不会继续执行后续的依赖注入。

不过跟下去可以看到,三个策略方法,底层就直接写死和返回了return true。

· org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(二)

代码语言:javascript
复制
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
   //...
   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
   boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
   if (hasInstAwareBpps || needsDepCheck) {
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      if (hasInstAwareBpps) {
         for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
               InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
               pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvs == null) {
                  return;
               }
            }
         }
      }
     //...
}

第六次调用后置处理器,进行属性依赖注入。

· org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)(一)

代码语言:javascript
复制
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
   //...
   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }
   //...
}
代码语言:javascript
复制
代码语言:javascript
复制
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
      result = beanProcessor.postProcessBeforeInitialization(result, beanName);
      if (result == null) {
         return result;
      }
   }
   return result;
}

第七次调用后置处理器,是在对bean进行初始化方法之前进行调用,执行postProcessBeforeInitialization方法。

· org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)(二)

代码语言:javascript
复制
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
   //...
代码语言:javascript
复制
    if (mbd == null || !mbd.isSynthetic()) {
       wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }  //...}
代码语言:javascript
复制
代码语言:javascript
复制
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
      result = beanProcessor.postProcessAfterInitialization(result, beanName);
      if (result == null) {
         return result;
      }
   }
   return result;
}

第八次调用后置处理器,是在对bean进行初始化方法之后进行调用,执行postProcessAfterInitialization方法。

· org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroyBean

代码语言:javascript
复制
protected void destroyBean(String beanName, DisposableBean bean) {
   //...
   if (bean != null) {
      try {
         bean.destroy();
      }
      catch (Throwable ex) {
         logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
      }
   }
代码语言:javascript
复制
   //...
}
代码语言:javascript
复制
@Override
public void destroy() {
   if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
      for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
         processor.postProcessBeforeDestruction(this.bean, this.beanName);
      }
   }
代码语言:javascript
复制
   //...
}

最后一次调用后置处理器,是在对bean的销毁方法之前对后置处理器的调用。

因此总共调用了九次后置处理器,前八次是在对bean进行初始化时候进行解析和调用。最后一次是在bean的销毁时进行的调用。

三、后置处理器调用总结

Spring中有一个特点就是方便扩展,而就是这些后置处理器可以帮助我们扩展需要处理的bean。

这九次后置处理器的调用通过流程图来总结:

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码云大作战 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档