BeanPostProcessor后置处理器原理与应用

BeanPostProcessor后置处理器原理与应用

BeanPostProcessor又叫后置处理器,是spring框架极其重要的概念。本身是个接口,接口里面定义了两个方法。许多扩展功能都是基于这种后置处理器的方式来实现的。spring框架会自动识别所有实现BeanPostProcessor接口的实现类,加载到容器中。当容器实例化完具体的一个bean后,会遍历所有实现接口的类,执行接口的实现方法,对刚刚实例化的bean进行初始化操作。

这只是最简单的应用,BeanPostProcessor还有几个子接口,可以实现在bean实例化前,后执行一些自定义操作。具体的用法和原理下面来分析。

1. BeanPostProcessor及相应子接口的应用

BeanPostProcessor就是为扩展,便于spring框架与其他应用整合。在容器内部和自定义的有很多子接口和实现类。这里介绍几个比较常用的子接口用法,具体的实现类太多,没办法一一介绍。

1.1 环境搭建

搭建一个spring环境,这里只是一个最基本的spring环境。

创建maven项目,依赖如下

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>

</dependencies>

使用java配置类的方式,创建一个启动类,一个用于测试的JavaBean和启动类

@Configuration
public class AppConfig {

    @Bean
    public User user()
    {
        return new User();
    }
}

public class User {

    private String name="li";

    public User(String name) {
        this.name = name;
    }

    public User() {
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

public class TestBean {

    public static void main(String[] args) {
         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Object bean = context.getBean("user");
        System.out.println(bean);
    }
}
1.1 BeanPostProcessor接口应用

创建一个实现BeanPostProcessor的类

public class MyBeanPostProcessor implements BeanPostProcessor {

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

        if (bean instanceof User) {
            System.out.println("postProcessBeforeInitialization中的bean:" + bean);
            User user = (User) bean;
            user.setName("曹操");
            return user;
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization中的bean:" + bean);
        return bean;
    }
}

在AppConfig配置类中添加配置将MyBeanPostProcessor注册容器中。

@Bean
public BeanPostProcessor beanPostProcessor() {

    return new MyBeanPostProcess();
}

启动TestBean中的Main方法,输出结果

postProcessBeforeInitialization中的bean:User{name='li'}
postProcessAfterInitialization中的bean:User{name='曹操'}
User{name='曹操'}

由上面结果可以得出结论

  • 容器会自动识别BeanPostProcessor的实现类,并自动调用
  • 容器会在bean实例化以后,执行接口中的方法
  • postProcessBeforeInitialization方法先执行,postProcessAfterInitialization后执行
  • 确实可以修改bean的属性
1.2 InstantiationAwareBeanPostProcessor接口应用

InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,在接口中增加了几个方法,创建一个InstantiationAwareBeanPostProcessor的实现类,并加入到容器中。BeanPostProcessor接口中的方法就不在重复实现了。

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("将beanName=user的bean类型改为Object,实例化");
        if (beanName.equals("user")) {
            return new Object();
        }
        return null;
    }

    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {

        System.out.println("postProcessAfterInstantiation执行");

        return true;
    }

    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {

        System.out.println("postProcessProperties执行");
        return null;
    }
}

在AppConfig配置类中添加配置将MyInstantiationAwareBeanPostProcessor注册容器中。

@Bean
public InstantiationAwareBeanPostProcessor instantiationAwareBeanPostProcessor()
{
    return new MyInstantiationAwareBeanPostProcessor();
}

启动TestBean中的Main方法,输出结果:

将beanName=user的bean类型改为Object,实例化
java.lang.Object@64d2d351

总结一下:

  • InstantiationAwareBeanPostProcessor接口中的postProcessBeforeInstantiation方法可以阻止bean正常实例化,甚至可以修改bean的类型,实际上spring的aop就是基于这个地方实现的
  • postProcessAfterInstantiation方法实在bean实例化之后,初始化之前调用的。并且如果postProcessBeforeInstantiation方法返回的不是null,postProcessAfterInstantiation和postProcessProperties方法都不会执行。可以自行测试。
2. BeanPostProcessor实现原理

说清楚BeanPostProcessor的实现原理需要学习spring源码,至少要了解spring容器的启动过程和bean的加载流程。这里只说明BeanPostProcessor的原理,不涉及其他方面的,我们直接看相关的源码。

其实BeanPostProcessor实现原理包括两个主要过程:

  • BeanPostProcessor的加载注册
  • BeanPostProcessor方法调用
2.1 BeanPostProcessor的加载注册

BeanPostProcessor的加载注册在spring容器启动实现的,看具体实现代码,当执行AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);代码时,会启动容器,这个过程中会执行加载BeanPostProcessor的代码。具体的加载逻辑如下,代码在PostProcessorRegistrationDelegate类中。

调用链路:

new AnnotationConfigApplicationContext(AppConfig.class)

​ refresh()

​ registerBeanPostProcessors(beanFactory)

​ PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this)

​ registerBeanPostProcessors

public static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

   //获取所有实现BeanPostProcessor接口的实现类的beanName
   String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

   //统计BeanPostProcessor的数量,包括内置的,上面查找到的,还有一个用于检查这些BeanPostProcessor的
   //BeanPostProcessorChecker
   int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
   beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

   //BeanPostProcessor分类,按PriorityOrdered,Ordered,正常顺序加载
    
   //实现按PriorityOrdered接口
   List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    
   //内部BeanPostProcessor
   List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    
   //实现按Ordered接口
   List<String> orderedPostProcessorNames = new ArrayList<>();
    
   //剩下的
   List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    
   //BeanPostProcessor分类
   for (String ppName : postProcessorNames) {
      if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
         priorityOrderedPostProcessors.add(pp);
         if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
         }
      }
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      else {
         nonOrderedPostProcessorNames.add(ppName);
      }
   }

   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);//排序
   registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);//注册

   List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
   for (String ppName : orderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      orderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);//排序
   registerBeanPostProcessors(beanFactory, orderedPostProcessors);//注册

   List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
   for (String ppName : nonOrderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      nonOrderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

   sortPostProcessors(internalPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, internalPostProcessors);

   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

总结一下流程:

  • 找到所有实现BeanPostProcessor接口的实现类

  • 将BeanPostProcessor分类,实现PriorityOrdered接口的先排序注册,然后是实现Ordered接口的,接着是正常的,最后是内部的,最后添加一个ApplicationListenerDetector。

  • 保存BeanPostProcessor的是一个List,可以按顺序遍历的

2.2 BeanPostProcessor的调用

BeanPostProcessor接口以及子接口InstantiationAwareBeanPostProcessor在bean的加载过程中调用的。这里我们可以以Object bean = context.getBean(“user”);为入口来学习。实际上并不是在这里执行的,这里的“user”bean在容器启动的最后一步加载的,只是执行加载bean的逻辑是一致的。

Object bean = context.getBean(“user”);跟下去会执行AbstractBeanFactory类中的doGetBean方法,这个方法涉及的逻辑比较复杂,与BeanPostProcessor不相关,所以不会详细分析,只是知道接下来会执行AbstractAutowireCapableBeanFactory类的createBean方法即可。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   if (logger.isTraceEnabled()) {
      logger.trace("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // Make sure bean class is actually resolved at this point, and
   // clone the bean definition in case of a dynamically resolved Class
   // which cannot be stored in the shared merged bean definition.
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   try {
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);  //这里真正实例化bean
      if (logger.isTraceEnabled()) {
         logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
   }
}

这个方法关注Object bean = resolveBeforeInstantiation(beanName, mbdToUse);这个方法上面有一个注释//Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.说的很清楚了,进入方法看一下。值得注意的是,如果执行这个逻辑返回的不是null,整个创建bean的流程就结束了,直接返回bean,不会走下面的流程。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
         Class<?> targetType = determineTargetType(beanName, mbd);
         if (targetType != null) {
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
         }
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

这个方法主要做一些判断验证逻辑,真正执行的后置处理器的逻辑是bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);这里有一个逻辑,如果执行bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);返回了不是null,才会执行InstantiationAwareBeanPostProcessor中的另一个方法postProcessAfterInitialization,在bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);中被调用。

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
   for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof InstantiationAwareBeanPostProcessor) {
         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
         Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
         if (result != null) {
            return result;
         }
      }
   }
   return null;
}

找到所有InstantiationAwareBeanPostProcessor实现对象,执行postProcessBeforeInstantiation方法。

如果上面的代码没有在Object bean = resolveBeforeInstantiation(beanName, mbdToUse);返回,会接续向下执行。在 Object beanInstance = doCreateBean(beanName, mbdToUse, args);真正的创建bean实例。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // Allow post-processors to modify the merged bean definition.
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            //这里其实也是一个后置处理器的子接口,在这调用
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

   // Eagerly cache singletons to be able to resolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      populateBean(beanName, mbd, instanceWrapper);
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
         throw (BeanCreationException) ex;
      }
      else {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }

   if (earlySingletonExposure) {
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         }
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name '" + beanName + "' has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been " +
                     "wrapped. This means that said other beans do not use the final version of the " +
                     "bean. This is often the result of over-eager type matching - consider using " +
                     "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   // Register bean as disposable.
   try {
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

在这里我们关注的是exposedObject = initializeBean(beanName, exposedObject, mbd);方法,提一句,当执行都这里时,bean已经被实例化,并且属性已经被装配完成。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
   if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);
         return null;
      }, getAccessControlContext());
   }
   else {
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   }
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}

这个方法执行初始化逻辑,关注三个方法;

  • applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

  • invokeInitMethods(beanName, wrappedBean, mbd);

  • applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

第一个和第三个方法就是执行BeanPostProcessor的连个方法,中间的进去看一下

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
      throws Throwable {

   boolean isInitializingBean = (bean instanceof InitializingBean);
   if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
      if (logger.isTraceEnabled()) {
         logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
      }
      if (System.getSecurityManager() != null) {
         try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
               ((InitializingBean) bean).afterPropertiesSet();
               return null;
            }, getAccessControlContext());
         }
         catch (PrivilegedActionException pae) {
            throw pae.getException();
         }
      }
      else {
         ((InitializingBean) bean).afterPropertiesSet();
      }
   }

   if (mbd != null && bean.getClass() != NullBean.class) {
      String initMethodName = mbd.getInitMethodName();
      if (StringUtils.hasLength(initMethodName) &&
            !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.isExternallyManagedInitMethod(initMethodName)) {
         invokeCustomInitMethod(beanName, bean, mbd);
      }
   }
}

这个方法是执行实现InitializingBean接口afterPropertiesSet方法调用,这在spring框架框架中应用也很多,通常是在bean实例化执行自己的一下初始化逻辑。

至此,BeanPostProcessor的实现原理分析结束。总结一下

2.3 总结

BeanPostProcessor及其子接口就是为了影响bean的实例化,初始化过程。在每个bean的加载流程中都会判定是否存在针对该bean类型的后置处理器,如果有执行处理程序。spring以及springboot的很多功能实现都是基于此,因此,理解BeanPostProcessor的原理对理解和使用spring框架非常重要。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值