spring后置处理器BeanPostProcessor
BeanPostProcessor的作用是在调用初始化方法的前后添加一些逻辑,这里初始化方法是指在配置文件中配置init-method,或者实现了InitializingBean接口的afterPropertiesSet方法,注意不包括@PostConstruct这种初始化方式。可以看源码AbstractAutowireCapableBeanFactory类中的invokeInitMethods方法。
1.用法
新建Student类
package com.demo.spring.entity; import javax.annotation.PostConstruct; import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component; /**
* @author chenyk
* @date 2018年5月8日
*/
@Component("student")
public class Student{
private String name;
private int age; private School school; public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
} public void init(){
System.out.println("执行 init方法");
} }
创建实现了BeanPostProcessor接口的后置处理器StudentBeanPostProcessor
package com.demo.spring.entity; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor; /**
* Bean后置处理器
* @author chenyk
* @date 2018年6月29日
*/
//以下这两个方法不能返回null,否则在调用初始化方法时会报空指针异常;因为后置处理器从springIOC容器中取出bean实例后需要再把bean实例放回去
public class StudentBeanPostProcessor implements BeanPostProcessor{ /**
* 在bean实例调用初始化方法之前调用
*/
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if(beanName.equals("student")){
System.out.println("开始调用init方法");
}
return bean;
} /**
* 在bean实例调用初始化方法之后调用
*/
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if(beanName.equals("student")){
System.out.println("init方法调用结束");
}
return bean;
}
}
在配置文件aop.xml中添加以下信息
<bean id="student" class="com.demo.spring.entity.Student" init-method="init" >
<property name="name" value="张三"></property>
</bean>
<!-- spring会自动检测实现了BeanPostProcessor接口的类,并将其注册为后置处理器 -->
<bean id="studentBeanPostProcessor" class="com.demo.spring.entity.StudentBeanPostProcessor" />
测试方法
@Test
public void testAop5(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop.xml");
}
看下打印信息:
开始调用init方法
2018-07-02 13:58:47,519 DEBUG [AbstractAutowireCapableBeanFactory.java:1731] : Invoking init method 'init' on bean with name 'student' //这一行信息,就是即将调用init-method方法的日志打印
执行 init方法
init方法调用结束
需要注意的是,如果一个类实现了BeanPostProcessor接口,那么这个类就作用于所有的bean实例,我们可以在BeanPostProcessor接口的两个方法中添加自己的控制和逻辑;
2.源码分析
2.1 找到实现BeanPostProcessor接口的类,并将其注册为后置处理器,看源码
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
//发现注册bean后置处理器,在这个方法中进行
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
initMessageSource(); // Initialize event multicaster for this context.
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
onRefresh(); // Check for listener beans and register them.
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
2.2 后置处理器生效的地方,进入AbstractAutowireCapableBeanFactory类中的initializeBean方法
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;
//后置处理器的postProcessBeforeInitialization方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//调用初始化方法有:init-method,实现了InitializingBean接口的方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
//后置处理器的postProcessAfterInitialization方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
3.最后,我们看下@PostConstruct执行的时间点。
进入AbstractAutowireCapableBeanFactory类的initializeBean方法
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()) {
//这个是后置处理器的方法,其实@PostConstruct是在CommonAnnotationBeanPostProcessor后置处理器的父类InitDestroyAnnotationBeanPostProcessor中实现的,
//也就是说@PostConstruct是由后置处理器来处理实现的,进入该方法
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;
}
进入applyBeanPostProcessorsBeforeInitialization方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//在循环中会发现一个类 CommonAnnotationBeanPostProcessor,然后进入其父类InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization该方法 进入该方法
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
进入postProcessBeforeinitialization方法
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//该类封装着一些通过注解的方式标识的初始化方法和销毁方法,以及相关属性
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
//@PostConstrutct注解就是在此处生效调用
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
spring后置处理器BeanPostProcessor的更多相关文章
- spring 后置处理器BeanFactoryPostProcessor和BeanPostProcessor的用法和区别
主要区别就是: BeanFactoryPostProcessor可以修改BEAN的配置信息而BeanPostProcessor不能,下面举个例子说明 BEAN类: package com.spring ...
- Spring点滴五:Spring中的后置处理器BeanPostProcessor讲解
BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...
- spring学习四:Spring中的后置处理器BeanPostProcessor
BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...
- Spring 后置处理器【1】
Spring 后置处理器[1] 简单介绍 一句话:bean 在初始化前或初始化后的瞬间,我自己添加一些业务逻辑 bean 后置处理器类的内容 简单代码 package com.hspedu.sprin ...
- Spring的后置处理器BeanPostProcessor
一.BeanPostProcessor接口的作用 如果我们需要在Spring容器完成Bean的实例化.配置和其他的初始化前后添加一些自己的逻辑处理,我们就可以定义一个或者多个BeanPostProce ...
- spring的后置处理器——BeanPostProcessor以及spring的生命周期
后置处理器的调用时机 BeanPostProcessor是spring提供的接口,它有两个方法——postProcessBeforeInitialization.postProcessAfterIni ...
- Bean后置处理器 BeanPostProcessor
1.BeanPostProcessor接口的作用 Bean后置处理器允许在调用初始化方法前后对Bean进行额外的处理,Bean后置处理器对IOC容器的所有bean实例逐一处理,而非单一实例. 我们可以 ...
- Spring 后置处理器 PropertyPlaceholderConfigurer 类(引用外部文件)
一.PropertyPlaceholderConfigurer类的作用 PropertyPlaceholderConfigurer 是 BeanFactory 后置处理器的实现,也是 BeanFact ...
- Spring中的后置处理器BeanPostProcessor讲解
Spring中提供了很多PostProcessor供开发者进行拓展,例如:BeanPostProcessor.BeanFactoryPostProcessor.BeanValidationPostPr ...
随机推荐
- (转)Spring Boot (十三): Spring Boot 小技巧
http://www.ityouknow.com/springboot/2017/06/22/spring-boot-tips.html 一些 Spring Boot 小技巧.小知识点 初始化数据 我 ...
- Pandas 拼接操作 数据处理
数据分析 生成器 迭代器 装饰器 (两层传参) 单例模式() ios七层 io多路 数据分析:是把隐藏在一些看似杂乱无章的数据背后的信息提炼出来,总结出所研究对象的内在规律 pandas的拼接操作 p ...
- cookie 处理 以及模拟登陆
cookie的处理 1.手动处理: cookie封装到headers 2.自动处理: 1.获取一个session对象 2.使用session对象进行请求的发送 3.作用:在使用session进行请求发 ...
- C#反射の一个泛型反射实现的网络请求框架
点击下载源码 C#反射の反射详解(点击跳转)C#反射の反射接口(点击跳转)C#反射反射泛型接口(点击跳转)C#反射の一个泛型反射实现的网络请求框架(点击跳转)
- Python打包—Pyinstaller
2018-09-27 21:12:05 一 前言 在windows平台学习python的过程中,你肯定会遇到需要把.py脚本打包成.exe的情形,如此,至少有两方面的好处:第一,你的代码保密性更好 ...
- SDOI2014 R1做题笔记
SDOI2014 R1做题笔记 经过很久很久的时间,shzr又做完了SDOI2014一轮的题目. 但是我不想写做题笔记(
- 1.java的基础和数据类型
一.学习要求1.听课一定要全神贯注2.课堂笔记,一定要自己总结,而且要有很严谨的逻辑关系.提纲很重要3.作业不折不扣的完成,并且多完成4.阶段项目一定要独立完成5.每天早上由一位同学来进行早分享,内容 ...
- Spring Security(八):2.4.3 Project Modules
In Spring Security 3.0, the codebase has been sub-divided into separate jars which more clearly sepa ...
- [BZOJ 3709] Bohater
Description 在一款电脑游戏中,你需要打败n只怪物(从1到n编号).为了打败第i只怪物,你需要消耗d[i]点生命值,但怪物死后会掉落血药,使你恢复a[i]点生命值.任何时候你的生命值都不能降 ...
- python:面向对象编程之Zope.interface安装使用
持续学习python+django中... 一.接口简述 在我们所熟知的面向对象编程语言中,大多提供了接口(interface)的概念.接口在编程语言中指的是一个抽象类型,是抽象方法的集合:它的特点如 ...