浅谈Spring中几个PostProcessor的区别与联系

目录
  • Spring几个PostProcessor的区别
    • 首先明确 Bean 的生命周期:
    • 查看 IOC 容器创建时的调用流程
  • spring-postProcessor的执行时机
    • BeanPostProcessor:
    • postProcessAfterInitialization调用时机:
    • InstantiationAwareBeanPostProcessor
    • 总结: 执行顺序

Spring几个PostProcessor的区别

首先明确 Bean 的生命周期:

  • 首先注册 Bean 的定义信息;
  • 然后创建 Bean 的实例;
  • 最后初始化 Bean ,放入容器中。

按照执行的顺序,可以分为以下几个步骤:

BeanDefinitionRegistryPostProcessor 是在注册 Bean 定义信息前后调用;

BeanFactoryPostProcessor 是在创建 Bean 前后调用;

BeanPostProcessor 是在初始化 Bean 前后调用;

其中 BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子类,所以可以使用前者代替后者实现功能。

查看 IOC 容器创建时的调用流程

refresh 方法的代码如下:

// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();

其中的 invokeBeanFactoryPostProcessors 就执行了注册定义信息和创建 Bean 的方法;而 finishBeanFactoryInitialization 执行了初始化 Bean 的方法。

具体的执行顺序大家可以自行打断点调试,由于涉及的源码过多,这里不再展示。

spring-postProcessor的执行时机

spring bean 的生命周期粗糙的分为以下步骤。

实例化(创建一个属性都为空的对象)---------》属性填充(populateBean,下文中这个步骤我都称为初始化)-----------》init方法的执行(invokerInitMethods,下文称为init)

postprocessor的方法就是穿插在这三个大的步骤中。

BeanPostProcessor:

postProcessBeforeInitialization调用时机

向上找调用者:

继续向上:

看以看出populateBean(初始化bean)-------------------》beanpostBeforeInitialization---------------------------------->invokeinitMethods(配置的init-method)

postProcessAfterInitialization调用时机:

向上:

可以看出在init-method方法之后

看以看出populateBean(初始化bean)-------------------》beanpostBeforeInitialization---------------------------------->invokeinitMethods(配置的init-method)------->postProcessAfterInitialization

public class MBeanPostProcessor implements BeanPostProcessor {
    @Override
    //populateBean之后   invokeinitMethods之前
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("post bean before! :"+beanName);
        return bean;
    }

    @Override
    //invokeinitMethods之后
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("post bean after!"+beanName);
        return bean;
    }
}

另一个重要的是:

InstantiationAwareBeanPostProcessor

postProcessBeforeInstantiation调用时机:

向上找调用者:

继续向上:

可以看出是在实例化之前:(也就是反射创建对象之前,如果postProcessBeforeInstantiation创建了一个非空的对象,则不会走实例化步骤。

postProcessAfterInstantiation调用时机:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   PropertyValues pvs = mbd.getPropertyValues();

   if (bw == null) {
      if (!pvs.isEmpty()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
         // Skip property population phase for null instance.
         return;
      }
   }

   // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
   // state of the bean before properties are set. This can be used, for example,
   // to support styles of field injection.
   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;
   }
 省略。。。。。
   applyPropertyValues(beanName, mbd, bw, pvs);
}

可以看出是在在初始化之前,具体是属性填充之前。(初始化之前,实例化之后) 如果返回fales,则不会继续初始化,即不会属性填充。

postProcessPropertyValues调用时机:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   PropertyValues pvs = mbd.getPropertyValues();
   if (bw == null) {
      if (!pvs.isEmpty()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
         // Skip property population phase for null instance.
         return;
      }
   }

   // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
   // state of the bean before properties are set. This can be used, for example,
   // to support styles of field injection.
   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;
   }

   if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

      // Add property values based on autowire by name if applicable.
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }

      // Add property values based on autowire by type if applicable.
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      }
      pvs = newPvs;
   }

   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;
               }
            }
         }
      }
      if (needsDepCheck) {
         checkDependencies(beanName, mbd, filteredPds, pvs);
      }
   }
   applyPropertyValues(beanName, mbd, bw, pvs);
}

在postProcessAfterInstantiation之后,applyPropertyValues之前。(属性填充之前修改属性值)

总结: 执行顺序

  • 1.postProcessBeforeInstantiation(实现这个方法可以做自定义实例化)
  • 2.实例化
  • 3.postProcessAfterInstantiation(是否要初始化)
  • 4.postProcessPropertyValues(修改属性)
  • 5.初始化(属性填充)(populateBean)
  • 6.postProcesstBeforeInitialization( 自定义init方法执行之前)
  • 7.invokeinitMethods(执行自定义的init方法)
  • 8.postProcessAfterInitialization(自定义init方法执行之后)

如果加上aware

  • 1.postProcessBeforeInstantiation(实现这个方法可以做自定义实例化)
  • 2.实例化
  • 3.postProcessAfterInstantiation(是否要初始化)
  • 4.postProcessPropertyValues(修改属性)
  • 5.初始化(属性填充)(populateBean)
  • 6.postProcesstBeforeInitialization( 自定义init方法执行之前)
  • 7.invokeAwareMethod
  • 8.invokeinitMethods(执行自定义的init方法)
  • 9.postProcessAfterInitialization(自定义init方法执行之后)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解使用Spring的BeanPostProcessor优雅的实现工厂模式

    最近学习Spring的源码,发现一个利器BeanPostProcessor.这个后置处理器可以在bean初始化前后对bean进行操作.我们可以在初始化的时候对自己想要的bean进行缓存,进而实现自己需要处理的逻辑. 背景 当我们需要根据类型调用接口不同实现的时候,我们可以使用工厂模式实现.下面说下博主遇到过的两次需要使用工厂的场景. 场景一: 当有一个模块,我们需要根据数据库的类型实现不同的的sql.我们此时需要定义一个接口然后每一种数据库实现不同的sql.在调用时根据当前的数据库类型调用对应的

  • 解析Java的Spring框架的BeanPostProcessor发布处理器

    BeanPostProcessor 的接口定义,可以实现提供自己的实例化逻辑,依赖解析逻辑等,也可以以后在Spring容器实例化完毕,配置和初始化一个bean通过插入一个或多个的BeanPostProcessor实现一些自定义逻辑回调方法实现. 可以配置多个的BeanPostProcessor接口,控制这些的BeanPostProcessor接口,通过设置属性顺序执行顺序提供的BeanPostProcessor实现了Ordered接口. BeanPostProcessor可以对bean(或对象)

  • Spring源码解析之BeanPostProcessor知识总结

    一.简介 BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口. 实例化Bean做前置处理.后置处理 二.接口定义 @Component public class BeanPost implements BeanPostProcessor { /** * 在每个bean创建之后的初始化方法之前调用 * @param bean 当前实例化的bean * @param beanName bean的名称 * @return 返回实例化的bean或者可以对对象进行再封装返

  • Spring BeanPostProcessor接口使用详解

    Spring中提供了很多PostProcessor供开发者进行拓展,例如:BeanPostProcessor.BeanFactoryPostProcessor.BeanValidationPostProcessor等一系列后处理器.他们的使用方式大多类似,了解其中一个并掌握他的使用方式,其他的可以触类旁通. 这里以BeanPostProcessor为例展示其使用方式. BeanPostProcessor接口提供了两个供开发者自定义的方法:postProcessBeforeInitializati

  • Spring容器的创建过程之如何注册BeanPostProcessor详解

    注册BeanPostProcessor refresh()调用registerBeanPostProcessors(beanFactory)方法,注册Bean的后置处理器,后置处理器是用来拦截bean创建过程的. 不同接口类型的BeanPostProcessor,即继承了BeanPostProcessor接口的子接口,在Bean创建前后的执行时机是不一样的 BeanPostProcessor DestructionAwareBeanPostProcessor InstantiationAware

  • Spring中的后置处理器BeanPostProcessor详解

    BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中. package com.test.spring; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.B

  • Spring的BeanFactoryPostProcessor接口示例代码详解

    接口简介 BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它. BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在

  • Spring注解驱动扩展原理BeanFactoryPostProcessor

    1.扩展原理-BeanFactoryPostProcessor BeanFactoryPostProcessor * 扩展原理: * BeanPostProcessor:bean后置处理器,bean创建对象初始化前后进行拦截工作的 * * 1.BeanFactoryPostProcessor:beanFactory的后置处理器: * 在BeanFactory标准初始化之后调用,来定制和修改BeanFactory的内容: * 所有的bean定义已经保存加载到beanFactory,但是bean的实

  • 浅谈Spring中几个PostProcessor的区别与联系

    目录 Spring几个PostProcessor的区别 首先明确 Bean 的生命周期: 查看 IOC 容器创建时的调用流程 spring-postProcessor的执行时机 BeanPostProcessor: postProcessAfterInitialization调用时机: InstantiationAwareBeanPostProcessor 总结: 执行顺序 Spring几个PostProcessor的区别 首先明确 Bean 的生命周期: 首先注册 Bean 的定义信息: 然后

  • 浅谈spring中的default-lazy-init参数和lazy-init

    在spring的配置中的根节点上有个  default-lazy-init="true"配置: 1.spring的default-lazy-init参数 此参数表示延时加载,即在项目启动时不会实例化注解的bean,除非启动项目时需要用到,未实例化的注解对象在程序实际访问调用时才注入调用 spring在启动的时候,default-lazy-init参数默认为false,会默认加载整个对象实例图,从初始化ACTION配置.到 service配置到dao配置.乃至到数据库连接.事务等等.这样

  • 浅谈spring中scope作用域

    今天研究了一下scope的作用域.默认是单例模式,即scope="singleton".另外scope还有prototype.request.session.global session作用域.scope="prototype"多例.再配置bean的作用域时,它的头文件形式如下: 如何使用spring的作用域: <bean id="role" class="spring.chapter2.maryGame.Role" s

  • 浅谈Spring中Bean的作用域、生命周期

    本文主要探究的是关于Bean的作用域.生命周期的相关内容,具体如下. Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).prototype(原型).request.session和global session,5种作用域说明如下: 1.singleton:单例模式,Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象.Singleton作用域是Spring中的缺省作用域,也可以显示的将Bean定义为

  • 浅谈Spring中@Import注解的作用和使用

    @Import用来导入@Configuration注解的配置类.声明@Bean注解的bean方法.导入ImportSelector的实现类或导入ImportBeanDefinitionRegistrar的实现类. @Import注解的作用 查看Import注解源码 /** * Indicates one or more {@link Configuration @Configuration} classes to import. * * <p>Provides functionality eq

  • 浅谈spring中isolation和propagation的用法

    可以在XML文件中进行配置,下面的代码是个示意代码 <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" isolation="READ_COMMITTED"/>增加记录的方法 <t

  • 浅谈Spring 中 @EnableXXX 注解的套路

    目录 前言 设计目标 @EnableScheduling (导入一个 @Configuration 类) @EnableTransactionManagement(导入一个 ImportSelector) @EnableAspectJAutoProxy (在 Bean 定义层导入) 结论 前言 在 Spring 框架中有很多实用的功能,不需要写大量的配置代码,只需添加几个注解即可开启. 其中一个重要原因是那些 @EnableXXX 注解,它可以让你通过在配置类加上简单的注解来快速地开启诸如事务管

  • 浅谈spring DI 依赖注入方式和区别

    目录 spring DI 3种DI注解的区别 1 @Autowired 2 @Inject 3 @Resource 3种注入方式的区别 1 field注入 2 构造器注入 3 setter注入 构造器注入的好处 1 依赖不可变 2 依赖不为空 3 完全初始化状态 4 避免循环依赖 5 总结 spring DI Spring框架对Java开发的重要性不言而喻,其核心特性就是IOC(Inversion of Control, 控制反转)和AOP,平时使用最多的就是其中的IOC,我们通过将组件交由Sp

  • 浅谈Java中Collection和Collections的区别

    1.java.util.Collection 是一个集合接口.它提供了对集合对象进行基本操作的通用接口方法.Collection接口在Java 类库中有很多具体的实现.Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式. Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set 2.java.util.Collections 是一个包装类.它包含有各种有关集合操作的静态多态方法.此类不能实例化,就像一

  • 浅谈php中urlencode与rawurlencode的区别

    前段时间说自己遇到了个<URL加号引发错误>的BUG,引起这个bug的原因就是自己在URL中使用了 urlencode 函数,该函数会把空格转换成加号,这样就导致URL解析出错,而空格只有转换成 %20 才可以可以正常解析,这时我们就需要使用 rawurlencode 函数. 下面就介绍一下 urlencode 函数与 rawurlencode 函数的区别: urlencode 函数: 返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格

随机推荐