Spring中BeanPostProcessor

Spring提供了很多擴展接口,BeanPostProcessor接口和InstantiationAwareBeanPostProcessor接口就是其中兩個。

 

BeanPostProcessor

BeanPostProcessor接口作用是:如果我們需要在Spring容器完成Bean的實例化、配置和其他的初始化前後添加一些自己的邏輯處理,我們就可以定義一個或者多個BeanPostProcessor接口的實現,然後註冊到容器中。

Spring中Bean的實例化過程圖示:

由上圖可以看到,Spring中的BeanPostProcessor在實例化過程處於的位置,BeanPostProcessor接口有兩個方法需要實現:postProcessBeforeInitialization和postProcessAfterInitialization,

Java代碼  收藏代碼
  1. import org.springframework.beans.factory.config.BeanPostProcessor;  
  2.    
  3. public class MyBeanPostProcessor implements BeanPostProcessor {  
  4.    
  5.      public MyBeanPostProcessor() {  
  6.         super();  
  7.         System.out.println("這是BeanPostProcessor實現類構造器!!");          
  8.      }  
  9.    
  10.      @Override  
  11.      public Object postProcessAfterInitialization(Object bean, String arg1)  
  12.              throws BeansException {  
  13.          System.out.println("bean處理器:bean創建之後..");  
  14.          return bean;  
  15.      }  
  16.    
  17.      @Override  
  18.      public Object postProcessBeforeInitialization(Object bean, String arg1)  
  19.              throws BeansException {  
  20.          System.out.println("bean處理器:bean創建之前..");  
  21.        
  22.          return bean;  
  23.      }  
  24.  }  
import org.springframework.beans.factory.config.BeanPostProcessor;
 
public class MyBeanPostProcessor implements BeanPostProcessor {
 
     public MyBeanPostProcessor() {
        super();
        System.out.println("這是BeanPostProcessor實現類構造器!!");        
     }
 
     @Override
     public Object postProcessAfterInitialization(Object bean, String arg1)
             throws BeansException {
         System.out.println("bean處理器:bean創建之後..");
         return bean;
     }
 
     @Override
     public Object postProcessBeforeInitialization(Object bean, String arg1)
             throws BeansException {
         System.out.println("bean處理器:bean創建之前..");
	 
         return bean;
     }
 }

 

BeanPostProcessor接口定義如下:

Java代碼  收藏代碼
  1. public interface BeanPostProcessor {  
  2.   
  3.     /** 
  4.      * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean 
  5.      * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} 
  6.      * or a custom init-method). The bean will already be populated with property values.    
  7.      */  
  8. //實例化、依賴注入完畢,在調用顯示的初始化之前完成一些定製的初始化任務  
  9.     Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;  
  10.   
  11.       
  12.     /** 
  13.      * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean 
  14.      * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}   
  15.      * or a custom init-method). The bean will already be populated with property values.       
  16.      */  
  17. //實例化、依賴注入、初始化完畢時執行  
  18.     Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;  
  19.   
  20. }  
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;

}

 

 

由方法名字也可以看出,前者在實例化及依賴注入完成後、在任何初始化代碼(比如配置文件中的init-method)調用之前調用;後者在初始化代碼調用之後調用。

注意:

1、接口中的兩個方法都要將傳入的bean返回,而不能返回null,如果返回的是null那麼我們通過getBean方法將得不到目標。

 

2、BeanFactory和ApplicationContext對待bean後置處理器稍有不同。ApplicationContext會自動檢測在配置文件中實現了BeanPostProcessor接口的所有bean,並把它們註冊爲後置處理器,然後在容器創建bean的適當時候調用它,因此部署一個後置處理器同部署其他的bean並沒有什麼區別。而使用BeanFactory實現的時候,bean 後置處理器必須通過代碼顯式地去註冊,在IoC容器繼承體系中的ConfigurableBeanFactory接口中定義了註冊方法:

 

Java代碼  收藏代碼
  1. /**  
  2.  * Add a new BeanPostProcessor that will get applied to beans created  
  3.  * by this factory. To be invoked during factory configuration.  
  4.  * <p>Note: Post-processors submitted here will be applied in the order of  
  5.  * registration; any ordering semantics expressed through implementing the  
  6.  * {@link org.springframework.core.Ordered} interface will be ignored. Note  
  7.  * that autodetected post-processors (e.g. as beans in an ApplicationContext)  
  8.  * will always be applied after programmatically registered ones.  
  9.  * @param beanPostProcessor the post-processor to register  
  10.  */    
  11. void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);   
/** 
 * Add a new BeanPostProcessor that will get applied to beans created 
 * by this factory. To be invoked during factory configuration. 
 * <p>Note: Post-processors submitted here will be applied in the order of 
 * registration; any ordering semantics expressed through implementing the 
 * {@link org.springframework.core.Ordered} interface will be ignored. Note 
 * that autodetected post-processors (e.g. as beans in an ApplicationContext) 
 * will always be applied after programmatically registered ones. 
 * @param beanPostProcessor the post-processor to register 
 */  
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor); 

 

 

另外,不要將BeanPostProcessor標記爲延遲初始化。因爲如果這樣做,Spring容器將不會註冊它們,自定義邏輯也就無法得到應用。假如你在<beans />元素的定義中使用了'default-lazy-init'屬性,請確信你的各個BeanPostProcessor標記爲'lazy-init="false"'。

 

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,可以在Bean生命週期的另外兩個時期提供擴展的回調接口,即實例化Bean之前(調用postProcessBeforeInstantiation方法)和實例化Bean之後(調用postProcessAfterInstantiation方法),該接口定義如下:
Java代碼  收藏代碼
  1. package org.springframework.beans.factory.config;    
  2.     
  3. import java.beans.PropertyDescriptor;    
  4.     
  5. import org.springframework.beans.BeansException;    
  6. import org.springframework.beans.PropertyValues;    
  7.     
  8. public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {    
  9.     
  10.     Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;    
  11.     
  12.     boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;    
  13.     
  14.     PropertyValues postProcessPropertyValues(    
  15.             PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)    
  16.             throws BeansException;    
  17.     
  18. }  
package org.springframework.beans.factory.config;  
  
import java.beans.PropertyDescriptor;  
  
import org.springframework.beans.BeansException;  
import org.springframework.beans.PropertyValues;  
  
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {  
  
    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;  
  
    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;  
  
    PropertyValues postProcessPropertyValues(  
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)  
            throws BeansException;  
  
}
 其使用方法與上面介紹的BeanPostProcessor接口類似,只時回調時機不同。
 
如果是使用ApplicationContext來生成並管理Bean的話則稍有不同,使用ApplicationContext來生成及管理Bean實例的話,在執行BeanFactoryAware的setBeanFactory()階段後,若Bean類上有實現org.springframework.context.ApplicationContextAware接口,則執行其setApplicationContext()方法,接着才執行BeanPostProcessors的ProcessBeforeInitialization()及之後的流程。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章