Spring BeanPostProcessor 究竟是如何工作的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29743320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:31:05  来源:igfitidea点击:

How exactly does the Spring BeanPostProcessor work?

springspring-mvcarchitecture

提问by AndreaNobili

I am studying for the Spring Core certification an I have some doubts about how Spring handle the beans lifecycleand in particular about the bean post processor.

我正在学习 Spring Core 认证,我对 Spring 如何处理bean 生命周期,特别是bean 后处理器有一些疑问。

So I have this schema:

所以我有这个架构:

enter image description here

在此处输入图片说明

It is pretty clear for me what it means:

我很清楚这意味着什么:

The following steps take place in the Load Bean Definitionsphase:

Load Bean Definitions阶段执行以下步骤:

  • The @Configurationclasses are processed and/or @Componentsare scanned for and/or XML filesare parsed.

  • Bean definitions added to BeanFactory (each indexed under its id)

  • Special BeanFactoryPostProcessorbeans invoked, it can modify the definition of any bean (for example for the property-placeholder values replacements).

  • @Configuration类被处理和/或@Components被扫描和/或XML文件进行解析。

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

  • 调用特殊的BeanFactoryPostProcessorbean,它可以修改任何 bean 的定义(例如用于属性占位符值的替换)。

Then the following steps take place in the beans creation phase:

然后在bean 创建阶段进行以下步骤:

  • Each bean is eagerly instantiated by default (created in right order with its dependencies injected).

  • After dependency injection each bean goes through a post-processing phase in which further configuration and initialization may occur.

  • After post processing the bean is fully initialized and ready for use (tracked by its id until the context is destroyed)

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

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

  • 后处理后,bean 完全初始化并准备好使用(由其 id 跟踪,直到上下文被销毁)

Ok, this is pretty clear for me and I also know that there are two types of bean post processorswhich are:

好的,这对我来说很清楚,我也知道有两种类型的 bean 后处理器

  • Initializers:Initialize the bean if instructed (i.e. @PostConstruct).

  • and All the rest:that allow for additional configuration and that may run before or after the initialize step

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

  • 所有其余的:允许额外的配置,并且可以在初始化步骤之前或之后运行

And I post this slide:

我发布了这张幻灯片:

enter image description here

在此处输入图片说明

So it is very clear for me what does the initializersbean post processors (they are the methods annotated with @PostContructannotation and that are automatically called immediately after the setter methods (so after the dependency injection), and I know that I can use to perform some initialization batch (as populate a cache as in the previous example).

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

But what exactly represents the other bean post processor? What do we mean when we say that these steps are performed before or after the initialization phase?

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

So my beans are instantiated and its dependencies are injected, so then the initialization phase is completed (by the execution of a @PostContructannotated method). What do we mean by saying that a Bean Post Processor is used before the initialization phase? It means that it happens before the @PostContructannotated method execution? Does it means that it could happen before the dependency injection (before that the setter methods are called)?

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

And what exactly do we mean when we say that it is performed after the initialization step. It means that it happens after that the execution of a @PostContructannotated method, or what?

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

I can easily figure into my head why I need a @PostContructannotated method but I can't figure some typical example of the other kind of bean post processor, can you show me some typical example of when are used?

我可以很容易地理解为什么我需要一个@PostContruct注释方法,但我无法弄清楚其他类型的 bean 后处理器的一些典型例子,你能告诉我一些什么时候使用的典型例子吗?

采纳答案by Master Slave

Spring doc explains the BPPs under Customizing beans using BeanPostProcessor. BPP beans are a special kind of beans that get created before any other beans and interact with newly created beans. With this construct, Spring gives you means to hook-up to and customize the lifecycle behavior simply by implementing a BeanPostProcessoryourself.

Spring 文档解释了使用 BeanPostProcessor 自定义 bean下的 BPP 。BPP bean 是一种特殊的 bean,它在任何其他 bean 之前创建并与新创建的 bean 交互。通过这种构造,Spring 为您提供了通过BeanPostProcessor自己实现一个来连接和自定义生命周期行为的方法。

Having a custom BPP like

有一个自定义的 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;
    }
}

would be called and print out the class and bean name for every created bean.

将被调用并打印出每个创建的 bean 的类和 bean 名称。

To undersand how the method fit the bean's lifecycle, and when exactly the method's get called check the docs

要了解该方法如何适应 bean 的生命周期,以及该方法的确切调用时间,请查看文档

postProcessBeforeInitialization(Object bean, String beanName)Apply this BeanPostProcessor to the given new bean instance before any bean initialization callbacks (like InitializingBean's afterPropertiesSet or a custom init-method).

postProcessAfterInitialization(Object bean, String beanName)Apply this BeanPostProcessor to the given new bean instance after any bean initialization callbacks (like InitializingBean's afterPropertiesSet or a custom init-method).

postProcessBeforeInitialization(Object bean, String beanName)在任何 bean 初始化回调(如 InitializingBean 的 afterPropertiesSet 或自定义初始化方法)之前,将此 BeanPostProcessor 应用于给定的新 bean 实例。

postProcessAfterInitialization(Object bean, String beanName)在任何 bean 初始化回调(如 InitializingBean 的 afterPropertiesSet 或自定义初始化方法)之后,将此 BeanPostProcessor 应用于给定的新 bean 实例。

The important bit is also that

重要的一点还在于

The bean will already be populated with property values.

bean 已经被填充了属性值。

For what concerns the relation with the @PostConstructnote that this annotation is a convenient way of declaring a postProcessAfterInitializationmethod, and Spring becomes aware of it when you either by registerCommonAnnotationBeanPostProcessoror specify the <context:annotation-config />in bean configuration file. Whether the @PostConstructmethod will execute before or after any other postProcessAfterInitializationdepends on the orderproperty

关于与@PostConstruct注释的关系,该注解是一种声明postProcessAfterInitialization方法的便捷方式,当您通过注册CommonAnnotationBeanPostProcessor或指定<context:annotation-config />in bean 配置文件时,Spring 会意识到这一点。该@PostConstruct方法是在任何其他方法之前还是之后执行postProcessAfterInitialization取决于order属性

You can configure multiple BeanPostProcessor instances, and you can control the order in which these BeanPostProcessors execute by setting the order property.

你可以配置多个 BeanPostProcessor 实例,你可以通过设置 order 属性来控制这些 BeanPostProcessor 的执行顺序。

回答by marthursson

The typical example for a bean post processor is when you want to wrap the original bean in a proxy instance, e.g. when using the @Transactionalannotation.

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

The bean post processor will be handed the original instance of the bean, it may call any methods on the target, but it also gets to return the actual bean instance that should be bound in the application context, which means that it can actually return any object it wants. The typical scenario when this is useful is when the bean post processor wraps the target in a proxy instance. All invocations on the bean bound in application context will pass through the proxy, and the proxy then gets to perform some magic before and/or after invocations on the target bean, e.g. AOP or transaction management.

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

回答by Tam Le

The difference is BeanPostProcessorwill hook into context initialization then call postProcessBeforeInitializationand postProcessAfterInitializationfor all defined beans.

不同之处在于BeanPostProcessor将挂钩到上下文初始化然后调用postProcessBeforeInitializationpostProcessAfterInitialization所有定义的bean。

But @PostConstructis just used for the specific class you want to customize bean creation after constructor or set method.

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