spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(01)

在spring中beanPostProcessor絕對是開天闢地的產物,給了程式設計師很多自主權,beanPostProcessor即常說的bean後置處理器。

一、概覽

先來說下InstantiationAwareBeanPostProcessor,這個後置處理器是BeanPostProcessor的子介面,繼承自BeanPostProcessor,先看下BeanPostProcessor中的方法,

再看下InstantiationAwareBeanPostProcessor中的方法,

可見InstantiationAwareBeanPostProcessor擴展了BeanPostProcessor介面,並且新增了4個方法,今天先看postProcessAfterInstantiation方法,

default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {          return true;      }

改方法有默認的返回值為true。

二、詳述

InstantiationAwareBeanPostProcessor中的postProcessAfterInstantiation方法的作用是什麼那,用在什麼地方。在看spring源碼的時候看到屬性注入這段程式碼,其中屬性注入是在populateBean方法中完成,在此方法中便出現了postProcessAfterInstatiation方法的調用,這裡只貼出populateBean方法中和這塊有關係的程式碼,

boolean continueWithPropertyPopulation = true;   //調用beanFactory中已註冊的beanPostProcessors即bean後置處理器,判斷是否為InstantiationAwareBeanPostProcessor的類型,如果是執行postProcessAfterInstantiation          if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {              for (BeanPostProcessor bp : getBeanPostProcessors()) {                  if (bp instanceof InstantiationAwareBeanPostProcessor) {                      InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//如果返回值為false才會進到下面的賦值操作,從而下方的1處才會為true,則屬性注入才會中斷
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } //1 if (!continueWithPropertyPopulation) { return; }

上面這段邏輯就是來循環已經註冊的beanPostProcessor,找到是InstantiationAwareBeanPostProcessor的類型,並執行其postProcessAfterInstantiation方法,通過查看已註冊的beanPostProcessor發現其返回值均為true,通過上面的分析,只有postProcessAfterInstantiation方法返回false,populateBean方法才會返回,屬性注入才會中斷,即不會注入值。

怎麼才能保證postProcessAfterInstantiation方法返回false那,這裡只有自己向spring註冊一個InstantiationAwareBeanPostProcessor的後置處理器,下面是我的一個後置處理器,

package cn.com.my.test;    import org.springframework.beans.BeansException;  import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;  import org.springframework.stereotype.Component;  @Component  public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {        @Override      public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {          // TODO Auto-generated method stub          System.out.println("beanName:"+beanName);          if("userService".equals(beanName)) {              return false;          }          return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);      }  }

自定義的beanPostProcessor僅實現了postProcessAfterInstantiation方法,上面的程式碼邏輯中,可以看到只有beanName為userService的時候,改方法才會返回false,其他情況下調用的介面方法,返回默認值true。

下面看我的測試類,

package cn.com.my.test;    import org.springframework.context.annotation.AnnotationConfigApplicationContext;    public class Test {        public static void main(String[] args) {          // TODO Auto-generated method stub            AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Config.class);            UserService us=ac.getBean(UserService.class);          System.out.println("us.roleService:"+us.getRoleService());      }    }

下面是我的UserService類,

package cn.com.my.test;    import org.springframework.beans.BeansException;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;  import org.springframework.stereotype.Component;    @Component  public class UserService {        @Autowired      private RoleService roleService;            public RoleService getRoleService() {          return roleService;      }        public void setRoleService(RoleService roleService) {          this.roleService = roleService;      }  }

從UserService類中,可以看出有一個加了註解的roleService屬性,正常情況下會自動注入改屬性,但在我自定義的beanPostProcessor之後,看下面的結果

神奇的事情,發生了us.roleService的屬性返回的null。

這是為什麼那,我們再看populateBean中的這段程式碼,

boolean continueWithPropertyPopulation = true;          //調用beanPostProcessors即bean後置處理器,          if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {              for (BeanPostProcessor bp : getBeanPostProcessors()) {                  if (bp instanceof InstantiationAwareBeanPostProcessor) {                      InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;                      if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {                          continueWithPropertyPopulation = false;                          break;                      }                  }              }          }            if (!continueWithPropertyPopulation) {              return;          }

由於,我們向beanFactory中註冊了一個beanPostProcessor,所以這裡循環的時候肯定會執行我的postProcessAfterInstantiation後置處理器,而我在後置處理器中進行了判斷,即在給beanName為userService進行屬性注入的時候postProcessAfterInstantiation方法會返回false,那麼上面的continueWithPropertyPopulation便為false,導致會進入到下面的if,方法直接返回,屬性注入便會中止,所以UserService類中的roleService的值為null。

三、適用場合

什麼時候需要實現InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法那,如果不想使用spring的自動注入(前提是已經使用了@Autowired註解),則對於特殊的bean則可以註冊一個beanPostProcessor使其不進行注入,使用自己的方式進行注入。

 

原創不易,有不當之處,歡迎指正,謝謝!