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

2020-08-26 17:20:43 浏览数 (1)

一、后置处理器简单示例

(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。

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

0 人点赞