Spring中提供了很多PostProcessor供开发者进行拓展,例如:BeanPostProcessor、BeanFactoryPostProcessor、BeanValidationPostProcessor等一系列后处理器。他们的使用方式大多类似,了解其中一个并掌握他的使用方式,其他的可以触类旁通。

BeanPostProcessor接口作用:

如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。

BeanPostProcessor API:

public interface BeanPostProcessor {  

    /**
* 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.
*/
//实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; /**
* 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.
*/
//实例化、依赖注入、初始化完毕时执行
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }

BeanPostProcessor接口提供了两个供开发者自定义的方法:postProcessBeforeInitialization、postProcessAfterInitialization。

postProcessBeforeInitialization:该方法主要针对spring在bean初始化时调用初始化方法前进行自定义处理。

postProcessAfterInitialization:该方法主要针对spring在bean初始化时调用初始化方法后进行自定义处理。

测试代码:

com.test.model.Cat:

package com.test.model;

/**
* 测试bean
*/
public class Cat {
private String name;
private int age; public void say() {
System.out.println("name:" + name);
System.out.println("age:" + age);
} 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;
}
}

spring容器中配置cat,和cat的beanPostProcessor:

<!--配置bean并初始化-->
<bean id="cat" class="com.test.model.Cat" >
<property name="name" value="HelloKitty" />
<property name="age" value="1" />
</bean>
<bean id="catBeanPostProcessor" class="com.test.postprocessor.CatBeanPostProcessor" />

com.test.postprocessor.CatBeanPostProcessor:

package com.test.postprocessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import com.test.model.Cat; /**
* 自定义后处理器
*/
public class CatBeanPostProcessor implements BeanPostProcessor{ @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Cat) {
//输出原始属性
Cat cat = (Cat) bean;
cat.say();
return bean;
}
return bean;
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Cat) {
//修改属性值,并返回
Cat cat = (Cat) bean;
cat.setName("hello maomi");
cat.setAge(3);
return cat;
}
return bean;
} }

IndexController:

package com.cy.controller;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest; import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.support.WebApplicationContextUtils; import com.test.model.Cat; @Controller
public class IndexController { //到index首页
@RequestMapping(value="index")
public String index(HttpServletRequest request){
/**
* 访问index同时,从容器中获取已经被初始化之后处理过的cat,打印信息
*/
ServletContext servletContext = request.getSession().getServletContext();
ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
Cat c = (Cat) ac.getBean("cat");
c.say(); return "index";
}
}

观察结果:

容器启动时,输出:

name:HelloKitty
age:1
访问项目http://localhost:8080/demo/index,index链接时,输出:
name:hello maomi
age:3
 
--------------------------------------------------------------------------------------------------------------------------
可以看到通过后处理器处理过后的bean信息已经改变。最后,看看源码中如何调用自定义实现的。
在初始化bean方法中:AbstractAutowireCapableBeanFactory.java
/**
* 初始化bean
*/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//省略部分无关代码
Object wrappedBean = bean;
//初始化前
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
} try {
//调用初始化方法初始化bean
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;
}
//postProcessBeforeInitialization方法调用
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//调用自定义postProcessBeforeInitialization方法
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
//postProcessAfterInitialization方法调用
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//自定义postProcessAfterInitialization方法调用
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

Spring中的后置处理器BeanPostProcessor讲解的更多相关文章

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

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

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

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

  3. spring中Bean后置处理器实现总结

    BeanPostProcessor接口 bean的后置处理器实现功能主要是 可以在bean初始化之前和之后做增强处理.自定义MyBeanProcessor实现BeanPostProcessor接口,重 ...

  4. Spring Bean前置后置处理器的使用

    Spirng中BeanPostProcessor和InstantiationAwareBeanPostProcessorAdapter两个接口都可以实现对bean前置后置处理的效果,那这次先讲解一下B ...

  5. Spring 如何保证后置处理器的执行顺序 - OrderComparator

    Spring 如何保证后置处理器的执行顺序 - OrderComparator Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.htm ...

  6. Spring的后置处理器BeanPostProcessor

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

  7. spring后置处理器BeanPostProcessor

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

  8. spring的后置处理器——BeanPostProcessor以及spring的生命周期

    后置处理器的调用时机 BeanPostProcessor是spring提供的接口,它有两个方法——postProcessBeforeInitialization.postProcessAfterIni ...

  9. Bean后置处理器 BeanPostProcessor

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

随机推荐

  1. ADOX创建ACCESS 表时,几个附加属性

     中文  英文 允许空字符串 Jet OLEDB:Allow Zero Length Unicode压缩 Jet OLEDB:Compressed UNICODE Strings 有效性规则 Jet ...

  2. Oracle导出空表解决办法

    在oracle 11g 中,发现传统的exp不能导出空的表 oracle 11g 新增了一个参数:deferred_segment_creation,含义是段延迟创建,默认是true.具体是什么意思呢 ...

  3. 百视通与微软共同宣布9月在华发布Xbox One

    4月30日消息,百视通今日与微软共同宣布,于今年9月在华发布Xbox One.这是继百视通与微软2013年9月成立合资公司后,双方合作的又一进展. 微软副总裁,硬件及设计工作室部门主管尤瑟夫 •梅赫迪 ...

  4. jQuery之阻止默认事件以及解除阻止

    大家都知道e.preventDefault()可以阻止默认时间,例如提交功能,但是怎么解除呢?以下参考于网络: 可以使用removeEventListener来移除.但是条件是addEventList ...

  5. java解决高并发

    1.redis ----------linkedblockQueue  rpop  lpush 2. 使用消息队列MQ 考虑到数据的一致性,队列的容量就是商品的剩余数量,队列采用的是线程安全的队列Li ...

  6. np.stack() 与 tf.stack() 的简单理解

    说明:np ----> numpy       tf ----> tensorflownp.stack(arrays, axis=0) np.stack(arrays, axis=0) - ...

  7. Centos编译Unix网络编程(第三版)卷1的源代码

    测试环境:Centos 1)在shell中输入./configure然后按回车(注意先让configure有执行权限 chomd 777 configure) 2)依次进入lib.libfree.li ...

  8. SpringAop与AspectJ

    AspectJ AspectJ是一个面向切面的框架,它扩展了Java语言.AspectJ定义了AOP语法,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件. spring ao ...

  9. 开源库dlib的安装与编译-CMake

    前言 最近项目涉及到关于face alignment的实现,了解到目前主要的算法有ERT.SDM.LBF等,其中由于dlib开源库实现了ERT算法,效果也很不错,故开始研究dlib的使用.而使用的第一 ...

  10. linux内核空间和用户空间详解

    linux驱动程序一般工作在内核空间,但也可以工作在用户空间.下面我们将详细解析,什么是内核空间,什么是用户空间,以及如何判断他们.Linux简化了分段机制,使得虚拟地址与线性地址总是一致,因此,Li ...