11 BeanPostProcessor
11.1 简介
BeanPostProcessor是Spring中定义的一个接口,其与之前介绍的InitializingBean和DisposableBean接口类似,也是供Spring进行回调的。Spring将在初始化bean前后对BeanPostProcessor实现类进行回调,与InitializingBean和DisposableBean接口不同的是BeanPostProcessor接口将对所有的bean都起作用,即所有的bean初始化前后都会回调BeanPostProcessor实现类,而InitializingBean和DisposableBean接口是针对单个bean的,即只有在对应的bean实现了InitializingBean或DisposableBean接口才会对其进行回调。
BeanPostProcessor接口的定义如下:
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
如你所见,BeanPostProcessor接口中定义了两个方法,其中方法postProcessBeforeInitialization()
将在一个bean被完全初始化前进行回调,此时对应的bean已经实例化了,但是对应的属性注入等还没有进行,即在调用InitializingBean的afterPropertiesSet()
方法或bean对应的init-method之前;而方法postProcessAfterInitialization()
将在bean被完全初始化后进行回调,此时对应的依赖注入已经完成,即在调用InitializingBean的afterPropertiesSet()
方法或对应init-method方法之后。两个方法的参数以及返回值对应的意义都是一样的,其中参数bean表示当前状态的bean,参数beanName表示当前bean的名称,而方法对应的返回值即表示需要放入到bean容器中的bean,所以用户如果有需要完全可以在这两个方法中对bean进行修改,即封装自己的bean进行返回。
以下是Spring源码中对bean进行初始化的逻辑,从源码中我们可以看到是先通过applyBeanPostProcessorsBeforeInitialization()
方法使用注册的BeanPostProcessor的postProcessBeforeInitialization()
方法依次回调,然后是通过invokeInitMethods()
方法依次调用当前bean对应的初始化方法,再通过applyBeanPostProcessorsAfterInitialization
方法使用注册的BeanPostProcessor的postProcessorAfterInitialization()
方法依次进行回调。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
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;
}
11.2 注册
BeanPostProcessor的注册是非常简单的,我们只需要把它当做一个普通的bean定义到Spring的bean容器中,Spring将能够自动检测到它,并将它注册到当前的bean容器中。BeanPostProcessor是容器绑定的,即BeanPostProcessor只能对跟它属于同一个bean容器中的bean进行回调,即BeanPostProcessor不能对属于它父容器或子容器中的bean进行回调。
在bean容器中定义了BeanPostProcessor之后,Spring将最先将BeanPostProcessor对应的bean进行实例化,如果我们制定BeanPostProcessor的lazy-initialization=”true”
或default-lazy-initialization=”true”
,Spring将对其进行忽略,即这些配置对BeanPostProcessor不起作用。这也很好理解,因为只有这样之后在实例化其它bean的时候这些BeanPostProcessor才能派上用场。鉴于这种机制,所以这里有一个问题需要注意,Spring在初始化bean的时候将优先初始化depends-on属性指定的bean,所以当我们的BeanPostProcessor通过depends-on指定了对其它bean的依赖时,其它bean是不会被BeanPostProcessor所回调的,当然这里也包括简介的depends-on对应的bean。此外,在BeanPostProcessor实例化后需要直接或间接的进行注入的bean也由于实例化时间提前不会被BeanPostProcessor回调。还有就是BeanPostProcessor之间不会进行回调,即BeanPostProcessorA不会在BeanPostProcessorB初始化时对其进行回调。
BeanPostProcessor在Spring内部也是用的比较多的,尤其是AOP代理部分。包括用户需要自己实现BeanPostProcessor实现代理功能时也需要注意BeanPostProcessor直接或间接关联的bean是不会被回调的,即不会被代理成功的。
11.3 示例
接下来看一个简单的定制自己的BeanPostProcessor的示例,在示例中我们将仅仅简单的实现一个BeanPostProcessor,在postProcessBeforeInitialization()
和postProcessAfterInitialization()
方法中都直接返回对应的bean,然后在postProcessBeforeInitialization()
方法中简单的打印一下对应的bean名称。
public class HelloBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("beanName-----------" + beanName);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
}
实现了BeanPostProcessor之后就可以将其定义到bean容器中,其定义方式跟普通bean的定义方式是一样的。
<bean class="com.app.HelloBeanPostProcessor"/>
11.4 回调顺序
在bean容器中我们可以同时定义多个BeanPostProcessor,这样在新实例化一个bean后将依次使用每个BeanPostProcessor回调一遍,当然,如果某一个BeanPostProcessor回调后的返回的bean为null,则不再继续往下回调,将直接返回null,这个时候bean容器中对应beanName对应的bean也是null。当在一个bean容器中同时定义有多个BeanPostProcessor时,默认将根据BeanPostProcessor在bean容器中定义的先后顺序对新实例化的bean进行回调。还有一种定义BeanPostProcessor回调顺序的方法是将我们自定义的BeanPostProcessor实现类同时实现Ordered接口,然后Spring将根据Ordered接口定义的getOrder()
方法的返回值来决定BeanPostProcessor回调的先后顺序,getOrder()
返回值越小的越先进行回调。此外,实现了Ordered接口的BeanPostProcessor总是比没有实现Ordered接口的BeanPostProcessor先进行回调,为了便于管理,推荐要么都实现Ordered接口,要么都不实现。
以下是一个实现了Ordered接口,并把getOrder()
方法的返回值作为一个参数进行配置的示例。
public class HelloBeanPostProcessor implements BeanPostProcessor, Ordered {
private int order;
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("beanName-----------" + beanName);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
public void setOrder(int order) {
this.order = order;
}
public int getOrder() {
return order;
}
}
之后就可以在配置的时候通过参数order来指定我们的getOrder()
方法的返回值。
<bean class="com.app.HelloBeanPostProcessor" p:order="3"/>
(注:本文是基于Spring4.1.0所写)
相关推荐
ResourceAware接口允许bean访问Spring的Resource对象,这些对象可以代表任何类型的资源,如文件、URL、数据库连接等。`setResource(Resource resource)`方法使得bean可以直接操作资源,增强了灵活性和可扩展性。 4...
Spring AOP 是一种面向切面编程的技术,它允许我们在不修改源代码的情况下,对应用程序的特定部分(如方法调用)进行增强。在 Spring 中,AOP 的实现主要依赖于代理模式,有两种代理方式:JDK 动态代理和 CGLIB 动态...
《Spring源码分析——ApplicationContext》 在Java世界中,Spring框架是不可或缺的一部分,它以其强大的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)特性,极大地...
Spring的扩展性非常强,支持自定义Bean后处理器(BeanPostProcessor)、Bean工厂后处理器(BeanFactoryPostProcessor)等,允许开发者在特定阶段介入Bean的生命周期。 7. **上下文的层次结构** ...
这些自定义的处理逻辑可以用来修改Bean的属性,检查Bean的依赖是否都已满足,或者是对Bean进行额外的处理。 要使用BeanPostProcessor,开发者需要编写一个实现了该接口的类,并且将该类的实例作为一个Bean注册到...
《Spring框架核心组件——Spring Beans详解》 Spring框架是Java领域中最广泛应用的轻量级框架之一,它以其IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)的核心特性...
虽然不是严格意义上的工厂模式,但Spring还提供了一种自定义Bean后处理的机制——`BeanPostProcessor`。开发者可以通过实现这个接口并在配置中注册,从而在Bean实例化之后、初始化之前或初始化之后进行定制操作。...
标题 "Spring IOC" 描述了我们讨论的核心主题——Spring 框架中的依赖注入(Inversion of Control,简称 IOC)机制。Spring 是一个广泛应用的 Java 应用开发框架,其核心特性之一就是IOC,它极大地简化了软件组件...
在初始化阶段,Spring会调用`BeanPostProcessor`的后处理方法,例如`postProcessBeforeInitialization()`和`postProcessAfterInitialization()`,允许用户自定义Bean的初始化行为。此外,还可以通过实现`...
Spring还提供了另一个扩展点——**BeanPostProcessor**,它允许我们对已经创建的Bean实例进行定制逻辑回调,比如在Bean创建后执行特定操作。 关于Bean的定制,有以下几种常见方式: 1. **Lifecycle Callback**:...
最后,Spring提供了一种更灵活的机制——`BeanPostProcessor`接口,它允许在bean初始化前后进行拦截和处理。`BeanPostProcessor`有两个关键方法:`postProcessBeforeInitialization()`和`...
Spring 使用 Bean 容器来管理对象,这些对象被称为 Beans。Bean 容器负责实例化、配置、装配以及管理这些 Beans。容器通过 XML、Java 注解或基于 Java 的配置来读取配置信息。 3. **AOP(面向切面编程)** Spring...
2. **BeanPostProcessor**:BeanPostProcessor是一个特殊的Bean,它可以在Bean的实例化前后进行拦截操作,常用于自定义Bean的初始化逻辑。 3. **BeanFactoryPostProcessor**:BeanFactoryPostProcessor是在...
Spring Bean的终极利器——BeanPostProcessor(BPP)接口,提供了一种强大的方式来扩展Spring容器的行为,允许我们在Bean实例化、属性设置、初始化方法调用等关键阶段进行干预。本文将深入讲解BPP的工作原理和应用...
首先,我们需要理解Spring框架的核心概念——Bean。在Spring中,Bean是被管理的对象,通常代表应用程序中的业务组件。Spring通过Bean工厂(BeanFactory)来管理和控制Bean的生命周期,包括实例化、初始化、配置和...
在这个系列的第一部分,我们将聚焦于Spring的核心——IoC容器的实现。本文将通过1000行代码,深入浅出地解释Spring IoC容器的工作原理,并尝试自己动手构建一个简易版的IoC容器。 IoC容器是Spring的核心,它负责...
### Spring源码解析:从IOC创建到Bean的注册 #### 概述 Spring框架作为Java领域内最流行的轻量级框架之一,...深入理解这些细节有助于开发者更好地利用Spring框架的强大功能,同时也能提高代码的可维护性和可扩展性。
当遇到`@Autowired`注解时,Spring会通过`AutowiredAnnotationBeanPostProcessor`进行处理,它实现了`BeanPostProcessor`接口,负责在Bean实例化之后进行后处理,包括依赖注入。 ### 8. 实战示例 在`...