spring扩展点二:自定义beanPostProcessor原理解析

beanPostProcessor是我在学习spring源码中,目前看到扩展最多的一个接口,比如:aop、spring事务、初始化方法回调,都是对该接口的扩展和实现,除了spring本身的框架,比如dubbo的ReferenceAnnotationBeanPostProcessor,这个扩展类就是一个后置处理器,用来解析@Reference注解的

bean后置处理器呢,spring在初始化bean的流程中,已经定义好了先执行后置处理器的哪个方法,后执行哪个方法,所以,我们在扩展的时候,要熟知这些方法执行位置以及先后顺序,根据这些,来明确自己的业务需求需要在哪个步骤进行扩展

我们只需要按照不同的beanPostProcess子类去实现即可

前言

不管是 我们实现的哪个扩展类,都需要考虑两个问题
1.我们扩展了之后,如果把我们自定义的扩展类放到spring容器中
2.放到容器中之后,是否会按照我们设想的步骤去调用
对于第一点,我们可以直接通过@Component注解,将beanPostProcessor作为一个普通的bean,放到beanDefinitionMap中即可,因为在spring启动的流程中,有一步是单独去注册初始化所有的后置处理器,
所以,对于第一点,我们只需要记住,只要将beanPostProcessor作为一个bean添加到beanDefinitionMap中即可,spring会自动帮我们去初始化这个后置处理器

对于第二点,我们提供了一个实现类之后,spring是如何将我们自己定义的beanPostProcessor作用于初始化过程中的呢?也和上面说的注册beanPostProcessor有关系,在spring将所有的后置处理器初始化之后,会将初始化好的后置处理器,放到一个集合中,spring在每次去调用后置处理器方法的时候,会从这个list集合中,获取到所有的符合条件的后置处理器,去过滤

其实对于spring中后置处理器的扩展机制原理,我觉得搞懂了这两句话,就全明白了

关于第一点,如何将我们提供的后置处理器放入到spring容器中,可以参考之前的笔记spring源码:注册后置处理器

注册后置处理器

第二点:
我们先说我们自定义的后置处理器,是存储在哪里的
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
这个方法,是spring来初始化所有后置处理器的,那其中在初始化完成之后,有一步比较关键的操作
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);

这三行代码,调用的是同一个逻辑,只是入参不同而已,看下方法的具体处理逻辑

private static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    
    

    for (BeanPostProcessor postProcessor : postProcessors) {
    
    
      beanFactory.addBeanPostProcessor(postProcessor);
    }
  }


  @Override
  public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    
    
    Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
    // Remove from old position, if any
    this.beanPostProcessors.remove(beanPostProcessor);
    // Track whether it is instantiation/destruction aware
    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
    
    
      this.hasInstantiationAwareBeanPostProcessors = true;
    }
    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
    
    
      this.hasDestructionAwareBeanPostProcessors = true;
    }
    // Add to end of list
    this.beanPostProcessors.add(beanPostProcessor);
  }

这里最为重要的是最后一行代码,将beanPostProcess放入到private final List beanPostProcessors = new CopyOnWriteArrayList<>();这个集合中,这个集合在后面的源码,我们还会看到,先有个印象

自定义的后置处理器如何生效

我们以第五个后置处理器方法org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
为例,这个方法是在属性注入之前被调用的,用来判断是否需要进行属性注入,
1、如果这个方法返回false,表示当前bean无需进行属性注入
2、那假如此时我有一个需求,需要对PayOrderService这个类进行处理,这个类中无需进行属性注入,这里我只是举一个例子,那此时,我就可以自己提供一个InstantiationAwareBeanPostProcessor的实现类,然后在实现类的postProcessAfterInstantiation()方法中,判断,如果当前初始化的bean是payOrderService,就返回false
3、需要注意的是,如果我们自己去扩展了实现类,一定要在实现方法中加上对bean的判断,否则,所有的bean都不会进行属性注入,为什么?因为每个bean在初始化的时候,都会调用我们自己的实现类,去判断是否要属性注入

这里有一个点要解释,为什么是InstantiationAwareBeanPostProcessor的方法,因为InstantiationAwareBeanPostProcessor继承了BeanPostProcessor,所以,这也是一个后置处理器的扩展接口;
针对第三点,一定要判断bean是否是自己要跳过属性注入的bean,可以去看下spring源码中,默认的实现方法,基本上都是返回true,都是需要属性注入的

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

boolean continueWithPropertyPopulation = true;

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;
      }
    }
  }
}

if (!continueWithPropertyPopulation) {
    
    
  return;
}

这一段代码,就是对postProcessAfterInstantiation的处理,可以看到,在源码中,会先判断当前beanDefinition是否是合成beanDefinition,然后再判断当前容器中,是否存在InstantiationAwareBeanPostProcessor的实现类

protected boolean hasInstantiationAwareBeanPostProcessors() {
    
    
  return this.hasInstantiationAwareBeanPostProcessors;
}

hasInstantiationAwareBeanPostProcessors在什么时候被赋值的?在上面注册后置处理器这里的addBeanPostProcessor方法中

判断完这些之后,会接着去遍历getBeanPostProcessors()返回的list集合

public List<BeanPostProcessor> getBeanPostProcessors() {
    
    
	return this.beanPostProcessors;
}

前面有说过,beanPostProcessors这个list会在后面出现使用到,就是这里
所以这里就解释了,我们自定义的beanPostProcess实现类,是如何生效的?
spring源码中,在每次进行后置处理器方法调用的时候,是会遍历容器中所有的后置处理器,依次调用其后置处理器方法进行处理

总结

最后做一个小总结吧,如果我们要扩展一个beanPostProcess的实现类,这个实现类要根据我们想要做的事情,来实现不同的beanPostProcess接口,然后通过@Component注解将实现类注入到spring容器中,就无需再做其他操作了,剩下的,spring就帮我们自己完成了调用
只是,我们在扩展的时候,需要明白自己扩展的业务逻辑要如何实现

猜你喜欢

转载自blog.csdn.net/CPLASF_/article/details/115079069
今日推荐