Spring的BeanFactoryPostProcessor和BeanPostProcessor
转载:http://blog.csdn.net/caihaijiang/article/details/35552859
BeanFactoryPostProcessor和BeanPostProcessor,这两个接口,都是spring初始化bean时对外暴露的扩展点。两个接口名称看起来很相似,但作用及使用场景却不同,分析如下:
1、BeanFactoryPostProcessor接口
该接口的定义如下:
- public interface BeanFactoryPostProcessor {
- /**
- * Modify the application context's internal bean factory after its standard
- * initialization. All bean definitions will have been loaded, but no beans
- * will have been instantiated yet. This allows for overriding or adding
- * properties even to eager-initializing beans.
- * @param beanFactory the bean factory used by the application context
- * @throws org.springframework.beans.BeansException in case of errors
- */
- void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
- }
实现该接口,可以在spring的bean创建之前,修改bean的定义属性。也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。
注意:BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的。接口方法的入参是ConfigurrableListableBeanFactory,使用该参数,可以获取到相关bean的定义信息,例子:
1)spring bean的定义:
- <?xml version="1.0" encoding="UTF-8" ?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
- default-autowire="byName">
- <bean id="myJavaBean" class="com.ali.caihj.postprocessor.MyJavaBean">
- <property name="desc" value="测试一下啦" />
- <property name="remark" value="这是备注信息啦啦啦" />
- </bean>
- <bean id="myBeanFactoryPostProcessor" class="com.ali.caihj.postprocessor.MyBeanFactoryPostProcessor" />
- </beans>
2)自定义的BeanFactoryPostProcessor:
- public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- System.out.println("调用MyBeanFactoryPostProcessor的postProcessBeanFactory");
- BeanDefinition bd = beanFactory.getBeanDefinition("myJavaBean");
- System.out.println("属性值============" + bd.getPropertyValues().toString());
- MutablePropertyValues pv = bd.getPropertyValues();
- if (pv.contains("remark")) {
- pv.addPropertyValue("remark", "把备注信息修改一下");
- }
- bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
- }
- }
spring中,有内置的一些BeanFactoryPostProcessor实现类,常用的有:
- org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
- org.springframework.beans.factory.config.PropertyOverrideConfigurer
- org.springframework.beans.factory.config.CustomEditorConfigurer:用来注册自定义的属性编辑器
2、BeanPostProcessor接口
该接口的定义如下:
- public interface BeanPostProcessor {
- /**
- * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
- * initialization callbacks (like InitializingBean's <code>afterPropertiesSet</code>
- * or a custom init-method). The bean will already be populated with property values.
- * The returned bean instance may be a wrapper around the original.
- * @param bean the new bean instance
- * @param beanName the name of the bean
- * @return the bean instance to use, either the original or a wrapped one
- * @throws org.springframework.beans.BeansException in case of errors
- * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
- */
- 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</code>
- * or a custom init-method). The bean will already be populated with property values.
- * The returned bean instance may be a wrapper around the original.
- * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
- * instance and the objects created by the FactoryBean (as of Spring 2.0). The
- * post-processor can decide whether to apply to either the FactoryBean or created
- * objects or both through corresponding <code>bean instanceof FactoryBean</code> checks.
- * <p>This callback will also be invoked after a short-circuiting triggered by a
- * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
- * in contrast to all other BeanPostProcessor callbacks.
- * @param bean the new bean instance
- * @param beanName the name of the bean
- * @return the bean instance to use, either the original or a wrapped one
- * @throws org.springframework.beans.BeansException in case of errors
- * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
- * @see org.springframework.beans.factory.FactoryBean
- */
- Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
- }
BeanPostProcessor,可以在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。这里说的初始化方法,指的是下面两种:
1)bean实现了InitializingBean接口,对应的方法为afterPropertiesSet
2)在bean定义的时候,通过init-method设置的方法
注意:BeanPostProcessor是在spring容器加载了bean的定义文件并且实例化bean之后执行的。BeanPostProcessor的执行顺序是在BeanFactoryPostProcessor之后。
spring中,有内置的一些BeanPostProcessor实现类,例如:
- org.springframework.context.annotation.CommonAnnotationBeanPostProcessor:支持@Resource注解的注入
- org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor:支持@Required注解的注入
- org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor:支持@Autowired注解的注入
- org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor:支持@PersistenceUnit和@PersistenceContext注解的注入
- org.springframework.context.support.ApplicationContextAwareProcessor:用来为bean注入ApplicationContext等容器对象
这些注解类的BeanPostProcessor,在spring配置文件中,可以通过这样的配置 <context:component-scan base-package="*.*" /> ,自动进行注册。(spring通过ComponentScanBeanDefinitionParser类来解析该标签)
3、下面通过完整的一个例子,来加深理解
1)定义一个JavaBean
- public class MyJavaBean implements InitializingBean {
- private String desc;
- private String remark;
- public MyJavaBean() {
- System.out.println("MyJavaBean的构造函数被执行啦");
- }
- public String getDesc() {
- return desc;
- }
- public void setDesc(String desc) {
- System.out.println("调用setDesc方法");
- this.desc = desc;
- }
- public String getRemark() {
- return remark;
- }
- public void setRemark(String remark) {
- System.out.println("调用setRemark方法");
- this.remark = remark;
- }
- public void afterPropertiesSet() throws Exception {
- System.out.println("调用afterPropertiesSet方法");
- this.desc = "在初始化方法中修改之后的描述信息";
- }
- public void initMethod() {
- System.out.println("调用initMethod方法");
- }
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("[描述:").append(desc);
- builder.append(", 备注:").append(remark).append("]");
- return builder.toString();
- }
- }
2)定义一个BeanFactoryPostProcessor
- public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- System.out.println("调用MyBeanFactoryPostProcessor的postProcessBeanFactory");
- BeanDefinition bd = beanFactory.getBeanDefinition("myJavaBean");
- MutablePropertyValues pv = bd.getPropertyValues();
- if (pv.contains("remark")) {
- pv.addPropertyValue("remark", "在BeanFactoryPostProcessor中修改之后的备忘信息");
- }
- }
- }
3)定义一个BeanPostProcessor
- public class MyBeanPostProcessor implements BeanPostProcessor {
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- System.out.println("BeanPostProcessor,对象" + beanName + "调用初始化方法之前的数据: " + bean.toString());
- return bean;
- }
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- System.out.println("BeanPostProcessor,对象" + beanName + "调用初始化方法之后的数据:" + bean.toString());
- return bean;
- }
- }
4)spring的配置
- <?xml version="1.0" encoding="UTF-8" ?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
- default-autowire="byName">
- <bean id="myJavaBean" class="com.ali.caihj.postprocessor.MyJavaBean" init-method="initMethod">
- <property name="desc" value="原始的描述信息" />
- <property name="remark" value="原始的备注信息" />
- </bean>
- <bean id="myBeanPostProcessor" class="com.ali.caihj.postprocessor.MyBeanPostProcessor" />
- <bean id="myBeanFactoryPostProcessor" class="com.ali.caihj.postprocessor.MyBeanFactoryPostProcessor" />
- </beans>
5)测试类
- public class PostProcessorMain {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("config/postprocessor.xml");
- MyJavaBean bean = (MyJavaBean) context.getBean("myJavaBean");
- System.out.println("===============下面输出结果============");
- System.out.println("描述:" + bean.getDesc());
- System.out.println("备注:" + bean.getRemark());
- }
- }
6)运行结果如下:
7)分析
从上面的结果可以看出,BeanFactoryPostProcessor在bean实例化之前执行,之后实例化bean(调用构造函数,并调用set方法注入属性值),然后在调用两个初始化方法前后,执行了BeanPostProcessor。初始化方法的执行顺序是,先执行afterPropertiesSet,再执行init-method。
Spring的BeanFactoryPostProcessor和BeanPostProcessor的更多相关文章
- Spring点滴十一:Spring中BeanFactoryPostProcessor和BeanPostProcessor区别
Spring中BeanFactoryPostProcessor和BeanPostProcessor都是Spring初始化bean时对外暴露的扩展点.两个接口从名字看起来很相似,但是作用及使用场景却不同 ...
- spring 后置处理器BeanFactoryPostProcessor和BeanPostProcessor的用法和区别
主要区别就是: BeanFactoryPostProcessor可以修改BEAN的配置信息而BeanPostProcessor不能,下面举个例子说明 BEAN类: package com.spring ...
- spring扩展点之一:BeanFactoryPostProcessor和BeanPostProcessor
一.BeanFactoryPostProcessor和BeanPostProcessor的区别 BeanFactoryPostProcessor和BeanPostProcessor都是spring初始 ...
- BeanFactoryPostProcessor vs BeanPostProcessor
BeanFactoryPostProcessors affect BeanDefinition objects because they are run right after your config ...
- Spring拓展接口之BeanPostProcessor,我们来看看它的底层实现
前言 开心一刻 小明:“妈,我被公司开除了”,妈:“啊,为什么呀?”, 小明:“我骂董事长是笨蛋,公司召开高层会议还要起诉我”,妈:“告你诽谤是吧?”,小明:“不是,他们说要告我泄露公司机密” Bea ...
- Spring Boot源码(五):BeanFactoryPostProcessor和BeanPostProcessor
BeanFactoryPostProcessor是spring BeanFactory加载Bean后调用, BeanPostProcessor是Bean初始化前后调用. BeanFactoryPost ...
- Spring 钩子之BeanFactoryPostProcessor和BeanPostProcessor的源码学习,FactoryBean
BeanFactoryPostProcessor 是用于增强BeanFactory的(例如可以增强beanDefination), BeanPostProcessor是用于增强bean的,而Facto ...
- Spring的后处理器-BeanPostProcessor跟BeanFactoryPostProcessors
最近在重读spring源码(为什么要重读?因为不得不承认,去年跟着<深入解析sping源码>一书过了一遍spring的源码,除了满脑袋都是各种BeanFactory跟BeanDefinit ...
- Spring笔记(6) - Spring的BeanFactoryPostProcessor探究
一.背景 在说BeanFactoryPostProcessor之前,先来说下BeanPostProcessor,在前文Spring笔记(2) - 生命周期/属性赋值/自动装配及部分源码解析中讲解了Be ...
随机推荐
- 2-sat按照最小字典序输出可行解(hdu1814)
Peaceful Commission Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- 是否可以继承String类?
是否可以继承String类? String类是final类故不可以继承
- WCF和Web Service的 区(guan)别(xi)
参考文献:http://social.microsoft.com/Forums/zh-CN/c06420d1-69ba-4aa6-abe5-242e3213b68f/wcf-webservice 之前 ...
- haskell笔记1
haskell platform下载:https://www.haskell.org/platform/ 进入haskell控制台,终端输入 $ ghci 编译文件 :l file.hs 数组操作 & ...
- oracle添加日志表
--创建表 CREATE TABLE KNET_DOMAIN_DNS_FORWARDED ( ID BYTE) DEFAULT sys_guid() NOT NULL , KEYWORD BYTE) ...
- PAT乙级 1019. 数字黑洞 (20)
1019. 数字黑洞 (20) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 给定任一个各位数字不完全相同的4位 ...
- [OrangePi] Features (the features of Loboris's Images)
boot0_sdcard.fex, u-boot.fex and kernel (uImage) created from sources kernel built with many feature ...
- 【sinatra】安装测试
$ gem install sinatra 测试: $ subl app.rb app.rb内容: require 'sinatra' get '/' do "Hello, World!&q ...
- JVM总结
1. 内存分布: 1). 程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.线程私有.如果线程正在执行的是一个J ...
- gerrit
https://en.wikibooks.org/wiki/Git/Gerrit_Code_Review http://openwares.net/linux/gerrit2_setup.html 不 ...