首页 > 代码库 > Spring Bean后处理器以及容器后处理器【转】

Spring Bean后处理器以及容器后处理器【转】

Bean后处理器:即当spring容器实例化Bean实例之后进行的增强处理。

容器后处理器:对容器本身进行处理,并总是在容器实例化其他任何Bean之前读取配置文件的元数据并可能修改这些数据。

 

一、Bean后处理器

      实现了BeanPostProcessor接口的类即可作为一个Bean后处理器,以下是一个Bean后处理器的范例

      1、编写一个实现了BeanPostProcessor接口的MyBeanPostProcessor类

 

[java] view plain copy
 
 技术分享技术分享
  1. package org.meify.core;  
  2.   
  3. import org.meify.bean.AuthorBean;  
  4. import org.springframework.beans.BeansException;  
  5. import org.springframework.beans.factory.config.BeanPostProcessor;  
  6. /** 
  7.  * Bean后处理器 
  8.  * 主要负责对容器初始化其他Bean后进行进一步增强处理 
  9.  * 当Spring容器实例化Bean实例之后,就偶会依次调用Bean后处理器的两个方法对实例Bean进行增强处理。 
  10.  * @description  
  11.  * @version 1.0 
  12.  * @author meify  2014-1-3 下午3:56:39 
  13.  */  
  14. public class MyBeanPostProcessor implements BeanPostProcessor {  
  15.     @Override  
  16.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  17.         // TODO Auto-generated method stub  
  18.         System.out.println(beanName+"初始化之前进行增强处理。。。");  
  19.         return bean;  
  20.     }  
  21.   
  22.     @Override  
  23.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
  24.         // TODO Auto-generated method stub  
  25.         System.out.println(beanName+"初始化之后进行增强处理。。。");  
  26.         //重新改编author实例的属性值  
  27.         if(beanName.equals("author")||bean instanceof AuthorBean){  
  28.             AuthorBean author=(AuthorBean) bean;  //获取要修改的bean对象
  29.             author.setAddress("辽宁省大连市");  
  30.         }  
  31.         return bean;  
  32.     }  
  33. }  


2、在spring配置文件中注册该Bean后处理器

 

 

[html] view plain copy
 
 技术分享技术分享
  1. <!-- 配置bean后置处理器,可以不配置id -->  
  2.     <bean id="beanProcessor" class="org.meify.core.MyBeanPostProcessor"/>  

 

 

至此一个Bean后处理器即完成了

 

二、容器后处理器

     同上,容器后处理器实现的是BeanFactoryPostProcessor接口

    1、编写实现了BeanFactoryPostProcessor接口的MyBeanFactoryPostProcessor的容器后处理器

   

[java] view plain copy
 
 技术分享技术分享
  1. package org.meify.core;  
  2.   
  3. import org.springframework.beans.BeansException;  
  4. import org.springframework.beans.factory.config.BeanFactoryPostProcessor;  
  5. import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;  
  6. /** 
  7.  * 容器后处理器 
  8.  * 通常用于对Spring容器进行拓展,并且总是在容器实例化其他任何bean之前读取配置文件的元数据并进行修改 
  9.  * 典型的应用即对数据源的配置,其中url  driver  user passwd等通常配置在properties文件中并使用属性占位符配置器来“填充” 
  10.  * @description  
  11.  * @version 1.0 
  12.  * @author meify  2014-1-3 下午4:31:12 
  13.  */  
  14. public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {  
  15.   
  16.     @Override  
  17.     public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {  
  18.         // TODO Auto-generated method stub  
  19.          System.out.println("对容器进行后处理。。。。");  
  20.     }  
  21.   
  22. }  


2、注册容器后处理器

[html] view plain copy
 
 技术分享技术分享
  1. <!-- 注册容器后处理器 -->  
  2.      <bean id="factoryProcessor" class="org.meify.core.MyBeanFactoryPostProcessor"/>  


这样一个容器后处理器也完成了

 

 

最后编写一个测试程序,对以上的两种后处理器进行测试

 

[java] view plain copy
 
 技术分享技术分享
  1. package org.meify.test;  
  2.   
  3.   
  4. import org.meify.bean.AuthorBean;  
  5. import org.springframework.context.ApplicationContext;  
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  7.   
  8. /** 
  9.  * 获取Spring容器并获取bean实例 
  10.  * 以下代码: 
  11.  * 先获取spring容器,再获取实体bean,将Spring接口与代码耦合在一起,造成代码污染。 
  12.  * @description  
  13.  * @version 1.0 
  14.  * @author meify  2014-1-2 下午2:33:48 
  15.  */  
  16. public class Test01 {  
  17.   
  18.     public static void main(String[] args) {  
  19.         //ApplicationContext的实例即Spring容器,也称之为Spring上下文  
  20.         ApplicationContext ctx=new ClassPathXmlApplicationContext("spring-config.xml");  
  21.         System.out.println(ctx);  
  22.           
  23.           
  24.           
  25.         AuthorBean author=ctx.getBean("author",AuthorBean.class);  
  26.         //注意,author的初始化时地址为湖北省武穴市,在Bean后处理器中改变为  辽宁省大连市  
  27.         System.out.println("author的地址为:===="+author.getAddress());  
  28.           
  29.           
  30.           
  31.         }  
  32.       
  33. }  


控制台输出如下:

 

 

[html] view plain copy
 
 技术分享技术分享
  1. 2014-1-3 16:33:24 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions  
  2. 信息: Loading XML bean definitions from class path resource [spring-config.xml]  
  3. 对容器进行后处理。。。。  
  4. 2014-1-3 16:33:24 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons  
  5. 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@c09554: defining beans [book,author,beanProcessor,factoryProcessor]; root of factory hierarchy  
  6. org.springframework.context.support.ClassPathXmlApplicationContext@1cb25f1: startup date [Fri Jan 03 16:33:24 CST 2014]; root of context hierarchy  
  7. author初始化之后进行增强处理。。。  
  8. 正在执行初始化方法。。。  
  9. author初始化之前进行增强处理。。。  
  10. author的地址为:====辽宁省大连市  



 

接下来介绍两个容器后处理器的范例。

拿之前的Spring管理数据源为例,使用容器后处理器进行改造。

1、属性占位符配置器

 

[html] view plain copy
 
 技术分享技术分享
  1. <!--  数据源配置 -->  
  2.    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  3.     <property name="driverClassName" value=http://www.mamicode.com/"${jdbc.driverClassName}" />  
  4.     <property name="url" value=http://www.mamicode.com/"${jdbc.url}" />  
  5.     <property name="username" value=http://www.mamicode.com/"${jdbc.username}" />  
  6.     <property name="password" value=http://www.mamicode.com/"${jdbc.password}" />  
  7.     <property name="initialSize" value=http://www.mamicode.com/"${jdbc.initialSize}" />  
  8.     <property name="maxActive" value=http://www.mamicode.com/"${jdbc.maxActive}" />  
  9.       
  10.     <property name="maxIdle" value=http://www.mamicode.com/"${jdbc.maxIdle}" />  
  11.     <property name="minIdle" value=http://www.mamicode.com/"${jdbc.minIdle}" />  
  12.     <property name="removeAbandoned" value=http://www.mamicode.com/"${jdbc.removeAbandoned}" />  
  13.     <property name="removeAbandonedTimeout" value=http://www.mamicode.com/"${jdbc.removeAbandonedTimeout}" />  
  14.     <property name="maxWait" value=http://www.mamicode.com/"${jdbc.maxWait}" />  
  15.     <property name="testOnBorrow" value=http://www.mamicode.com/"${jdbc.testOnBorrow}" />  
  16.     <property name="validationQuery" value=http://www.mamicode.com/"${jdbc.validationQuery}" />  
  17.     <property name="testWhileIdle" value=http://www.mamicode.com/"${jdbc.testWhileIdle}" />  
  18.     <property name="timeBetweenEvictionRunsMillis" value=http://www.mamicode.com/"${jdbc.timeBetweenEvictionRunsMillis}" />  
  19.     <property name="numTestsPerEvictionRun" value=http://www.mamicode.com/"${jdbc.numTestsPerEvictionRun}" />  
  20. </bean>   


其中属性占位符处理器的注册

 

 

[html] view plain copy
 
 技术分享技术分享
  1. <!--  注意PropertyPlaceholderConfigurer——属性占位符配置器,  
  2.                          它作为容器的后处理器将properties文件中配置的属性值填到相应的占位符处 -->  
  3.      <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  4.          <property name="locations">  
  5.              <list>  
  6.                 <value>classpath*:DB.properties</value>  
  7.              </list>  
  8.          </property>  
  9.     </bean>   

 

 

其中数据源配置properties文件内容如下:

 

[plain] view plain copy
 
 技术分享技术分享
  1. ### MySQL-\u4e3b\u6570\u636e\u5e93 ###  
  2. jdbc.driverClassName=com.mysql.jdbc.Driver  
  3. jdbc.url=jdbc:mysql://10.3.17.22:3306/neuonline?autoReconnect=true&useUnicode=true&characterEncoding=utf8  
  4. jdbc.username=neuonline  
  5. jdbc.password=neuonline  
  6. #\u521d\u59cb\u5316\u8fde\u63a5 \u6570\u91cf  
  7. jdbc.initialSize = 10  
  8. #\u6700\u5927\u53ef\u7528\u8fde\u63a5\u6570\u91cf  
  9. jdbc.maxActive = 200  
  10. #\u6700\u5927\u7a7a\u95f2\u8fde\u63a5  
  11. jdbc.maxIdle=100  
  12. #\u6700\u5c0f\u7a7a\u95f2\u8fde\u63a5  
  13. jdbc.minIdle=50  
  14. #\u662f\u5426\u81ea\u52a8\u79fb\u9664\u65e0\u6548\u7684\u8fde\u63a5  
  15. jdbc.removeAbandoned=true  
  16. #\u79fb\u9664\u65e0\u6548\u7684\u8fde\u63a5 \u8d85\u65f6\u65f6\u95f4(\u4ee5\u79d2\u6570\u4e3a\u5355\u4f4d)  
  17. jdbc.removeAbandonedTimeout=120  
  18. #\u8d85\u65f6\u7b49\u5f85\u65f6\u95f4\u4ee5\u6beb\u79d2\u4e3a\u5355\u4f4d 6000\u6beb\u79d2/1000\u7b49\u4e8e60\u79d2  
  19. jdbc.maxWait=5000  
  20. #\u662f\u5426\u83b7\u53d6\u8fde\u63a5\u65f6\u8fdb\u884c\u6d4b\u8bd5  
  21. jdbc.testOnBorrow=true  
  22. #\u6d4b\u8bd5\u6570\u636e\u5e93\u6b63\u5e38\u4e0e\u5426\u7684\u8bed\u53e5  
  23. jdbc.validationQuery=SELECT now()  
  24. #\u6d4b\u8bd5\u7a7a\u95f2\u94fe\u63a5\u662f\u5426\u53ef\u4ee5\u6b63\u5e38\u8bbf\u95ee  
  25. jdbc.testWhileIdle=true  
  26. #\u6d4b\u8bd5\u7a7a\u95f2\u94fe\u63a5\u6d4b\u8bd5\u65f6\u95f4\uff08\u6beb\u79d2\uff09\u95f4\u9694  
  27. jdbc.timeBetweenEvictionRunsMillis=1800000  
  28. #\u6d4b\u8bd5\u7a7a\u95f2\u94fe\u63a5\u7684\u6570\u91cf\uff08\u540cjdbc.maxActive\u4fdd\u6301\u4e00\u81f4\uff09  
  29. jdbc.numTestsPerEvictionRun=200  



这样属性占位符配置器会在容器初始化后,任何其他bean实例化之前将数据源中占位处使用properties文件中的属性值替换。

 

 

2、重写占位符配置器

将上面 的配置分别进行修改即可,改动部分如下:

 

[html] view plain copy
 
 技术分享技术分享
  1. <bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">  
  2.         <property name="locations">  
  3.             <list>  
  4.                <value>classpath*:dbconn.properties</value>  
  5.             </list>  
  6.         </property>  
  7.    </bean>  

 

[html] view plain copy
 
 技术分享技术分享
  1. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"/>  

 

 

最后编写测试程序测试获取到的数据库连接

 

[java] view plain copy
 
 技术分享技术分享
  1. package org.meify.test;  
  2.   
  3. import org.springframework.context.ApplicationContext;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5. import java.sql.SQLException;  
  6.   
  7. import javax.sql.DataSource;  
  8. /** 
  9.  * 测试获取数据库连接 
  10.  * @description  
  11.  * @version 1.0 
  12.  * @author meify  2014-1-3 下午2:15:20 
  13.  */  
  14. public class Test03 {  
  15.     public static void main(String[] args) throws SQLException {  
  16.         ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");  
  17.         DataSource ds = (DataSource) ctx.getBean("dataSource", DataSource.class);  
  18.         java.sql.Connection conn = ds.getConnection();  
  19.         System.out.println(conn);  
  20.     }  
  21.   
  22. }  

控制台输出:

 

 

[java] view plain copy
 
 技术分享技术分享
    1. jdbc:mysql://10.3.17.22:3306/neuonline?autoReconnect=true&useUnicode=true&characterEncoding=utf8, UserName=neuonline@10.1.242.79, MySQL-AB JDBC Driver  

Spring Bean后处理器以及容器后处理器【转】