Spring BeanPostProcessor究竟是如何工作的?

时间:2015-04-20 08:57:45

标签: spring spring-mvc architecture

我正在研究Spring Core认证,我对Spring如何处理 beans生命周期,特别是 bean post post 有一些疑问。

所以我有这个架构:

enter image description here

我很清楚这意味着什么:

以下步骤发生在加载Bean定义阶段:

  • 处理 @Configuration 类和/或 @Component}

  • 扫描扫描和/或 XML文件

  • 添加到BeanFactory的Bean定义(每个都在其id下编制索引)

  • 调用了特殊的 BeanFactoryPostProcessor bean,它可以修改任何bean的定义(例如,对于property-placeholder值替换)。

然后,在 bean创建阶段中执行以下步骤:

  • 默认情况下,每个bean都会被急切地实例化(以正确的顺序创建并注入其依赖项)。

  • 依赖注入后,每个bean都经过后处理 可能发生进一步配置和初始化的阶段。

  • 在后期处理之后,bean已完全初始化并可以使用(由id跟踪,直到上下文被销毁)

好的,这对我来说非常清楚,我也知道有两种类型的bean后处理器,它们是:

  • 初始化程序:如果指示(即@PostConstruct),则初始化bean。

  • 所有其余,允许进行其他配置,可以在初始化步骤之前或之后运行

我发布这张幻灯片:

enter image description here

所以我很清楚初始化器 bean后处理器是什么(它们是用 @PostContruct 注释注释的方法,并且在setter之后立即自动调用方法(因此在依赖注入之后),我知道我可以用来执行一些初始化批处理(如前面的例子中那样填充缓存)。

但究竟什么代表了其他bean后处理器?当我们说这些步骤在初始化阶段之前或之后执行时,我们的意思是什么?

因此我的bean被实例化并注入其依赖项,因此初始化阶段完成(通过执行 @PostContruct 带注释的方法)。在初始化阶段之前使用Bean Post处理器是什么意思?这意味着它发生在 @PostContruct 带注释的方法执行之前?这是否意味着它可能在依赖注入之前发生(在调用setter方法之前)?

当我们说在初始化步骤后执行时,我们到底意味着什么呢?这意味着它会在执行 @PostContruct 带注释的方法之后发生,或者是什么?

我可以很容易地想到为什么我需要一个 @PostContruct 带注释的方法,但是我无法想象其他类型的bean后处理器的一些典型示例,你能告诉我一些吗?使用何时的典型例子?

3 个答案:

答案 0 :(得分:34)

Spring doc解释了Customizing beans using BeanPostProcessor下的BPP。 BPP bean是一种特殊的bean,它在任何其他bean之前创建并与新创建的bean交互。通过这种结构,Spring可以让您通过自己实现BeanPostProcessor来连接和自定义生命周期行为。

拥有类似

的自定义BPP
public class CustomBeanPostProcessor implements BeanPostProcessor {

    public CustomBeanPostProcessor() {
        System.out.println("0. Spring calls constructor");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }
}
将调用

并打印出每个创建的bean的类和bean名称。

要说明该方法如何适应bean的生命周期,以及何时调用该方法,请检查docs

  

postProcessBeforeInitialization(Object bean,String beanName) Apply   这个BeanPostProcessor在任何bean之前到达给定的新bean实例   初始化回调(如InitializingBean的afterPropertiesSet   或自定义init方法。

     

postProcessAfterInitialization(Object bean,String beanName) Apply   这个BeanPostProcessor在任何bean之后到达给定的新bean实例   初始化回调(如InitializingBean的afterPropertiesSet   或自定义init方法。

重要的一点也是那个

  

bean已经填充了属性值。

关于与@PostConstruct的关系的注意事项,注意这个注释是一种声明postProcessAfterInitialization方法的便捷方式,当你通过注册CommonAnnotationBeanPostProcessor或者注册<context:annotation-config />时,Spring会意识到它在bean配置文件中指定@PostConstructpostProcessAfterInitialization方法在任何其他order之前或之后执行是否取决于{{1}}属性

  

您可以配置多个BeanPostProcessor实例   通过设置来控制这些BeanPostProcessors执行的顺序   订单属性。

答案 1 :(得分:23)

bean后处理器的典型示例是当您想要将原始bean包装在代理实例中时,例如使用@Transactional注释时。

bean post处理器将被传递给bean的原始实例,它可以调用目标上的任何方法,但它也会返回应该绑定在应用程序上下文中的实际bean实例,这意味着它可以实际上返回它想要的任何对象。这很有用的典型场景是bean后处理器将目标包装在代理实例中。在应用程序上下文中绑定的bean上的所有调用都将通过代理,然后代理在目标bean的调用之前和/或之后执行一些魔术,例如, AOP或交易管理。

答案 2 :(得分:2)

差异是BeanPostProcessor将挂钩到上下文初始化,然后为所有定义的bean调用postProcessBeforeInitializationpostProcessAfterInitialization

@PostConstruct仅用于在构造函数或set方法之后自定义bean创建的特定类。