SpringBeanPostProcessor 到底是如何工作的?

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

所以我有这样一个模式:

enter image description here

对我来说,这意味着什么非常清楚:

LoadBean 定义阶段采取了以下步骤:

  • 处理 @ 配置类和/或 @ 组件类 扫描和/或解析 XML 文件

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

  • 调用了特殊的 BeanFactory 后处理器 bean,它可以修改任何 bean 的定义(例如对于属性占位符值的替换)。

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

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

  • 每颗依赖注入经过后期处理 进一步配置和初始化可能发生的阶段

  • 在后期处理之后,bean 被完全初始化并准备好使用(通过它的 id 跟踪,直到上下文被销毁)

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

  • 初始化器: 初始化 bean,如果指示的话(例如@PostConstruction)。

  • 其他的:,允许额外的配置和 可以在初始化步骤之前或之后运行

我发布了这张幻灯片:

enter image description here

所以对我来说,什么是 初始化程序 bean 后期处理器是非常清楚的(它们是带有 @ PostConstruction注释的方法,在 setter 方法之后会立即自动调用(在依赖注入之后) ,我知道我可以用它来执行一些初始化批处理(就像在前面的例子中填充缓存一样)。

但是什么确切地表示另一个 bean 后处理程序呢?当我们说这些步骤是执行 在初始化阶段之前或之后时,我们的意思是什么?

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

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

我可以很容易地想到为什么我需要一个 @ PostConstruction注释的方法,但我不能指出其他类型的 bean 后处理器的一些典型例子,你能给我一些什么时候使用的典型例子吗?

62507 次浏览

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 BeanPostProcessor yourself.

Having a custom BPP like

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.

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

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).

The important bit is also that

The bean will already be populated with property values.

For what concerns the relation with the @PostConstruct note that this annotation is a convenient way of declaring a postProcessAfterInitialization method, and Spring becomes aware of it when you either by registerCommonAnnotationBeanPostProcessor or specify the <context:annotation-config /> in bean configuration file. Whether the @PostConstruct method will execute before or after any other postProcessAfterInitialization depends on the order property

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

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 @Transactional annotation.

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.

The difference is BeanPostProcessor will hook into context initialization then call postProcessBeforeInitialization and postProcessAfterInitialization for all defined beans.

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