BeanPostProcessor

在Bean的属性被Spring容器设定之后,您还有机会自订一些对Bean的修正,您可以实现org.springframework.beans.factory.config.BeanPostProcessor界面:

   package org.springframework.beans.factory.config;
   public interface BeanPostProcessor {
       public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException;
       public Object postProcessAfterInitialization(Object bean, String name) throws BeansException;
   }

postProcessBeforeInitialization()方法会在Bean初始化动作之前(例如InitializingBean的 afterPropertiesSet()方法或自定义的init方法)被呼叫,而postProcessAfterInitialization()方法会在Bean初始化之后立即被呼叫。

举个例子来说,您可以实现一个大写修正器,对于String型态的Bean属性,无论在定义档中是设定为大写或小写,在Bean属性设定之后,您可以在大写修正器中将所有的String改为大写,例如:

  • UpperCaseModifier.java
   package onlyfun.caterpillar;
   
   import java.lang.reflect.Field;
   
   import org.springframework.beans.BeansException;
   import org.springframework.beans.factory.config.BeanPostProcessor;
   
   public class UpperCaseModifier implements BeanPostProcessor {
   
       public Object postProcessBeforeInitialization(
                           Object bean, String name) throws BeansException {
           Field[] fields = bean.getClass().getDeclaredFields();
           
           for(int i = 0; i < fields.length; i++) {
               if(fields[i].getType().equals(String.class)) {
                   fields[i].setAccessible(true);
                   try {
                       String original = (String) fields[i].get(bean);
                       fields[i].set(bean, original.toUpperCase());
                   } catch (IllegalArgumentException e) {
                       e.printStackTrace();
                   } catch (IllegalAccessException e) {
                       e.printStackTrace();
                   }
               }
           }
           
           return bean;
       }
   
       public Object postProcessAfterInitialization(
                             Object bean, String name) throws BeansException {
           return bean;
       }
   
   }

假设您定义了这么一个Bean类别:

  • HelloBean.java
   package onlyfun.caterpillar; 
   
   public class HelloBean { 
       private String helloWord; 
       
       public HelloBean() {
       }
       
       public void setHelloWord(String helloWord) { 
           this.helloWord = helloWord; 
       } 
       public String getHelloWord() { 
           return helloWord; 
       } 
   }

ApplicationContext会自动侦测您是否在定义档中定义了实现BeanPostProcessor接口的类别,例如:

  • beans-config.xml
   <?xml version="1.0" encoding="UTF-8"?> 
   <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" 
     "http://www.springframework.org/dtd/spring-beans.dtd"> 
   
   <beans>  
       <bean id="upperCaseModifier" 
             class="onlyfun.caterpillar.UpperCaseModifier"/>
       
       <bean id="helloBean" class="onlyfun.caterpillar.HelloBean"> 
           <property name="helloWord"> 
               <value>Hello!</value> 
           </property> 
       </bean>
   </beans>

Spring容器会在每一个Bean被初始化之前之后分别呼叫upperCaseModifier的 postProcessBeforeInitialization()方法与postProcessAfterInitialization()方法,以 对Bean进行指定的相关修正,可以实际来看看以下的测试程序:

  • SpringDemo.java
   package onlyfun.caterpillar; 
   
   import org.springframework.context.ApplicationContext;
   import org.springframework.context.support.FileSystemXmlApplicationContext; 
   
   public class SpringDemo { 
       public static void main(String[] args) { 
           ApplicationContext context = 
               new FileSystemXmlApplicationContext("beans-config.xml");
            
           HelloBean hello = 
               (HelloBean) context.getBean("helloBean");
           System.out.println(hello.getHelloWord());
       } 
   }

执行结果如下:

   HELLO!

虽然您在定义文件中的helloBean之helloWord属性是设定小写字母,但upperCaseModifier将之改为大写字母了。