做一个合格的程序猿之浅析Spring IoC源码(四)分析BeanPostProcessor(1)

转自:http://blog.csdn.net/linuu/article/details/50846058


BeanPostProcessor是什么呢,有什么作用呢,打开源代码先看看

做一个合格的程序猿之浅析Spring IoC源码(四)分析BeanPostProcessor(1)

这个接口的注释中原作者说明了该接口的作用:

“工厂钩子允许用户自定义修改创建的bean实例,应用上下文可以在ben的定义中自动检测beanPostProecessor,并且将其应用于随后创建的任意bean中,并且可以通过factory给其他的类进行注册然后使用”

说白了,就是我们可以自定义的去修改spring给我们创建的类,给了我们一个二次修改bean的机会,这种设计思路与spring的“开闭原则”相符合,没有过度分装,举例来说,我们根据beanDefinition去查找一个Teacher,找到之后spring给我们实例化这个Teacher,但是我们用这个teacher的时候,发现这个teacher会抽烟,我们可以修改这个老师会抽烟的属性,这样就得到了一个完美的老师,这个完美的老师授课结束后,我们再告诉他你可以接着抽烟了,所以spring给我们想的还是很周到的~

 


再看这个接口定义的2个方法

做一个合格的程序猿之浅析Spring IoC源码(四)分析BeanPostProcessor(1)

BeanPostProcessor这个接口就2个方法,根据这2个方法的名称,我们就大概知道这2个方法的做什么的了

postProcessBeforeInitialization在“初始化之前处理”

postProcessAfterInitialization在“初始化之后处理”


废话不多说,我们就实现一个上面讲述的例子,大家更加深入的理解一下BeanPostProcessor这个作用

Teacher.java

  1. package org.study.spring.beanpostprocessor.demo;  
  2.   
  3. public class Teacher {  
  4.       
  5.     /** 
  6.      * 老师的姓名 
  7.      */  
  8.     private String name;  
  9.       
  10.     /** 
  11.      * 年龄 
  12.      */  
  13.     private int age;  
  14.       
  15.     /** 
  16.      * 是否抽烟 
  17.      */  
  18.     private boolean smoking;  
  19.       
  20.     /** 
  21.      * 老师教授的课程 
  22.      */  
  23.     private String language;  
  24.       
  25.     /** 
  26.      * 临时变量,默认抽烟 
  27.      */  
  28.     private boolean tempSmoking = true;  
  29.       
  30.       
  31.     public Teacher() {  
  32.           
  33.     }  
  34.        
  35.     public boolean isTempSmoking() {  
  36.         return tempSmoking;  
  37.     }  
  38.   
  39.   
  40.     public void setTempSmoking(boolean tempSmoking) {  
  41.         this.tempSmoking = tempSmoking;  
  42.     }  
  43.   
  44.   
  45.     public String getName() {  
  46.         return name;  
  47.     }  
  48.   
  49.     public void setName(String name) {  
  50.         this.name = name;  
  51.     }  
  52.   
  53.     public int getAge() {  
  54.         return age;  
  55.     }  
  56.   
  57.     public void setAge(int age) {  
  58.         this.age = age;  
  59.     }  
  60.   
  61.     public boolean isSmoking() {  
  62.         return smoking;  
  63.     }  
  64.   
  65.     public void setSmoking(boolean smoking) {  
  66.         this.smoking = smoking;  
  67.     }  
  68.   
  69.   
  70.     public String getLanguage() {  
  71.         return language;  
  72.     }  
  73.   
  74.     public void setLanguage(String language) {  
  75.         this.language = language;  
  76.     }  
  77.       
  78.     public void teach(){  
  79.         System.out.println("I am :"+name+" and I will teach you :"+language + " and I "+(tempSmoking?"will":"will not")+" smoking");  
  80.     }  
  81.       
  82.   
  83. }  

ChangeTeacherSmokingBeanPostProcessor.java
  1. package org.study.spring.beanpostprocessor.demo;  
  2.   
  3. import org.springframework.beans.BeansException;  
  4. import org.springframework.beans.factory.config.BeanPostProcessor;  
  5.   
  6. public class ChangeTeacherSmokingBeanPostProcessor implements BeanPostProcessor{  
  7.       
  8.   
  9.     /** 
  10.      * 初始化之前处理 
  11.      */  
  12.     public Object postProcessBeforeInitialization(Object bean, String beanName)  
  13.             throws BeansException {  
  14.         /** 
  15.          * 只处理该bean的类型是Teacher的 
  16.          */  
  17.         if(bean instanceof Teacher){  
  18.             Teacher teacher = (Teacher)bean;  
  19.             /** 
  20.              * 实例化之前,要吧所有抽烟的都改成不抽烟的 
  21.              */  
  22.             if(teacher.isSmoking()){  
  23.                 ((Teacher)bean).setTempSmoking(false);  
  24.             }  
  25.         }  
  26.         return bean;  
  27.     }  
  28.   
  29.     public Object postProcessAfterInitialization(Object bean, String beanName)  
  30.             throws BeansException {  
  31.         return bean;  
  32.     }  
  33.   
  34. }  

bean-post-processor-teacher.xml
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"  
  5.     xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
  7.         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd  
  8.         http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd  
  9.         http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd  
  10.         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">  
  11.    
  12.         <bean id="teacher" class="org.study.spring.beanpostprocessor.demo.Teacher">  
  13.           <property name="name" value="孔浩"/>  
  14.           <property name="age" value="32"/>  
  15.           <property name="smoking" value="true"/>  
  16.           <property name="language" value="java"/>  
  17.         </bean>  
  18.           
  19.         <bean id="changeTeacher" class="org.study.spring.beanpostprocessor.demo.ChangeTeacherSmokingBeanPostProcessor"/>  
  20.             
  21.   
  22. </beans>  
ChangeTeacherSmokingBeanPostProcessorTest.java
  1. package org.study.spring.beanpostprocessor.demo;  
  2.   
  3. import org.junit.Test;  
  4. import org.springframework.context.ApplicationContext;  
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  6.   
  7. public class ChangeTeacherSmokingBeanPostProcessorTest{  
  8.       
  9.       
  10.     @Test  
  11.     public void test2() throws Exception{  
  12.          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-post-processor-teacher.xml");  
  13.          Teacher teacher = applicationContext.getBean("teacher",Teacher.class);  
  14.          teacher.teach();  
  15.            
  16.     }  
  17.   
  18. }  

运行结果

做一个合格的程序猿之浅析Spring IoC源码(四)分析BeanPostProcessor(1)


上面的例子只是说明,spring在初始化之前,给了我们开发者二次修改的机会,beanPostProcessor这个类是“spring”开闭原则的典型实现,下一节详细讲述它在项目中的具体运用~