后置处理器的调用时机

BeanPostProcessor是spring提供的接口,它有两个方法——postProcessBeforeInitialization、postProcessAfterInitialization。关于这两个方法的调用时机,可以参考spring源码注释。

    /**
* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
} /**
* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}

从源码注释中可以看出,postProcessBeforeInitialization方法会在bean实例化和属性设置之后,自定义初始化方法(参考https://www.cnblogs.com/dubhlinn/p/10664402.html提到的3种方式)之前被调用,而postProcessAfterInitialization方法会在自定义初始化方法之后被调用。当容器中存在多个BeanPostProcessor的实现类时,会按照它们在容器中注册的顺序执行。对于自定义BeanPostProcessor实现类,还可以让其实现Ordered接口自定义排序。

后置处理器的注册方式

在ApplicationContext容器中,只需要按普通的bean注册即可;

但是在BeanFactory容器中,需要显示的调用addBeanPostProcessor()方法才能注册。

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered; /**
* 自定义后置处理器
* 用于在bean的初始化前后进行扩展
* 这里的初始化,指的是初始化阶段调用的方法,
* 例如@Bean注解的initMethod、spring提供的InitializingBean接口、jsr-250提供的@PostConstruct接口
* 当容器中存在多个后置处理器时,默认会按照其在容器中注册的顺序执行
* 对于自定义后置处理器,也可以通过实现Ordered接口来自定义其执行顺序,数字越大优先级越低
*/
public class AppleBeanPostProcessor implements BeanPostProcessor, Ordered { /**
* 在初始化前执行的扩展逻辑
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("apple".equals(beanName)) {
System.out.println("创建了苹果对象...");
}
return bean;
} /**
* 在初始化后执行的扩展逻辑
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("apple".equals(beanName)) {
System.out.println("苹果对象初始化完成...");
}
return bean;
} @Override
public int getOrder() {
return 3;
}
}
/**
* 用注册普通bean的方式注册自定义后置处理器
*/
@Configuration
@Import(value = {AppleBeanPostProcessor.class})
public class LifeBeanConfig2 {
}

后置处理器的作用

简单的说,后置处理器用于bean对象初始化前后进行逻辑增强。spring提供了BeanPostProcessor的很多实现类,例如AutowiredAnnotationBeanPostProcessor用于@Autowired注解的实现,AnnotationAwareAspectJAutoProxyCreator用于SpringAOP的动态代理等等。除此之外,我们还可以自定义BeanPostProcessor的实现类,在其中写入需要的逻辑。下面以AnnotationAwareAspectJAutoProxyCreator为例,说明后置处理器是怎样工作的。我们都知道springAOP的实现原理是动态代理,最终放入容器的是代理类的对象,而不是bean本身的对象,那么spring是什么时候做到这一步的?就是在AnnotationAwareAspectJAutoProxyCreator后置处理器的postProcessAfterInitialization方法,即bean对象初始化完成之后,后置处理器会判断该bean是否注册了切面,如果是,则生成代理对象注入容器

    /**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

spring的生命周期

所谓spring的生命周期,是指一个bean对象在容器中从创建到销毁的过程,大致会经历如下过程:

1. 执行bean的构造方法,生成bean对象

2. 执行bean的set方法,注入属性

3. 如果容器中存在BeanPostProcessor的实现类,则执行它们的postProcessorBeforeInitialization方法

4. 如果bean实现了InitializingBean接口,则执行afterPropertiesSet方法

5. 如果<bean>标签或@Bean注解中定义了init-method/initMethod,则执行其引用的方法

6. 如果容器中存在BeanPostProcessor的实现类,则执行它们的postProcessorAfterInitialization方法

7. 关闭容器时,如果bean实现了DisposableBean接口,则执行destroy方法

8. 关闭容器时,如果<bean>标签或@Bean注解中定义了destroy-method/destroyMethod,则执行其引用的方法

spring的后置处理器——BeanPostProcessor以及spring的生命周期的更多相关文章

  1. Spring的后置处理器BeanPostProcessor

    一.BeanPostProcessor接口的作用 如果我们需要在Spring容器完成Bean的实例化.配置和其他的初始化前后添加一些自己的逻辑处理,我们就可以定义一个或者多个BeanPostProce ...

  2. Spring点滴五:Spring中的后置处理器BeanPostProcessor讲解

    BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...

  3. spring学习四:Spring中的后置处理器BeanPostProcessor

    BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...

  4. spring利用后置处理器初始化bean属性

    spring利用后置处理器初始化bean属性 参考:http://blog.csdn.net/heyutao007/article/details/50326793 @Configurable @En ...

  5. spring后置处理器BeanPostProcessor

    BeanPostProcessor的作用是在调用初始化方法的前后添加一些逻辑,这里初始化方法是指在配置文件中配置init-method,或者实现了InitializingBean接口的afterPro ...

  6. Spring Bean后置处理器

    本例子源于:W3CSchool,在此作记录 Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理. BeanPostProcessor 接口定义回调方法,你可以实现该方法来提供自己 ...

  7. 曹工杂谈:为什么很少需要改Spring源码,因为扩展点太多了,说说Spring的后置处理器

    前言 最近发了好几篇,都是覆盖框架源码,但是spring的代码,我是从没覆盖过,毕竟,如果方便扩展,没谁想去改源码,而spring就是不需要改源码的那个,真的是"对扩展开放,对修改关闭&qu ...

  8. Spring Bean 后置处理器

    Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理. BeanPostProcessor 接口定义回调方法,你可以实现该方法来提供自己的实例化逻辑,依赖解析逻辑等. 你也可以在 ...

  9. Bean后置处理器 BeanPostProcessor

    1.BeanPostProcessor接口的作用 Bean后置处理器允许在调用初始化方法前后对Bean进行额外的处理,Bean后置处理器对IOC容器的所有bean实例逐一处理,而非单一实例. 我们可以 ...

随机推荐

  1. 第三方模块:gulp模块

    一.Gulp的使用 1. 使用npm install  gulp  下载gulp库文件 2. 在项目根目录下简历gulpfile.js文件 3. 重构项目的文件夹架构src目录放置源代码文件,dist ...

  2. C/C++ 内存与指针

    内存与指针杂谈 1.指针 1.数组指针 int(*ptr)[n] ()的优先级高,(*ptr)表示ptr是一个指针,指向一个int类型的一维数组,这个数组的长度为n,也可以说ptr的步长就是n.也就是 ...

  3. Mysql 服务器管理程序 mysqladmin

    mysqladmin [oprions] command 选项                                      说明 create db_name               ...

  4. Thinkphp5 自定义分页样式显示页码和数量

    Thinkphp5 自带的分页比较简单,本文通过修改Bootstrap类自定义显示分页的页码和数量 一.修改完成后如下图显示 二.修改Bootstrap代码: 1.为了不改动Bootstrap.php ...

  5. linux c下的c文件 h文件 o文件 so文件 a文件 可执行文件 gcc使用

    linux下c语言工程: c文件:主要每个模块的原代码都在c文件中. h文件:每个c文件都跟着一个h文件,h文件的作用是放着c文件中函数的声明,结构体的定义,宏的定义等. o文件:目标文件.每个文件经 ...

  6. 自然语言处理资源NLP

    转自:https://github.com/andrewt3000/DL4NLP Deep Learning for NLP resources State of the art resources ...

  7. AT Regular 086

    C - Not so Diverse 略 D - Non-decreasing 先找绝对值最大的数 构造出全正(最大的数为正) 或者全负(最大的数为负) 然后前缀和(正)或者后缀和(负) 操作次数2n ...

  8. 开发过程中git的使用

    使用clone命令可以直接将git添加到本地库: 主要是针对分支的操作: 首先可以将创建一个属于自己的分支并往上面提交代码,最后合并到dev分支和master分支上面: 前提(master已经有一个文 ...

  9. margin-top百分比问题

    (1)其实margin-top和margin-bottom的百分比,一般是按容器元素的宽度而不是高度来计算的,padding同理.

  10. js 获取滚动位置,滚动到指定位置,平滑滚动

    1.获取当前滚动条位置信息 var top = dom.scrollTop; // 获取y轴上的滚动位置 var left = dom.scrollLeft; // 获取x轴上的滚动位置 2.滚动到指 ...