spring源碼分析系列 (3) spring拓展接口InstantiationAwareBeanPostProcessor

更多文章點擊--spring源碼分析系列html

 

主要分析內容:java

1、InstantiationAwareBeanPostProcessor簡述與demo示例git

2、InstantiationAwareBeanPostProcessor與BeanPostProcessor對比spring

3、InstantiationAwareBeanPostProcessor源碼分析:註冊時機和觸發點app

(源碼基於spring 5.1.3.RELEASE分析)框架

 

1、InstantiationAwareBeanPostProcessor簡述與demo示例ide

 InstantiationAwareBeanPostProcessor繼承自BeanPostProcessor 是spring很是重要的拓展接口,表明這bean的一段生命週期: 實例化(Instantiation函數

 1 public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {  2     
 3  @Nullable  4     default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {  5         return null;  6  }  7 
 8     default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {  9         return true; 10  } 11 
12  @Nullable 13     default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) 14             throws BeansException { 15 
16         return null; 17  } 18 
19  @Deprecated 20  @Nullable 21     default PropertyValues postProcessPropertyValues( 22             PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { 23 
24         return pvs; 25  } 26 
27 }

 

因爲InstantiationAwareBeanPostProcessor繼承自BeanPostProcessor, 其餘接口能夠參考spring源碼分析系列 (2) spring拓展接口BeanPostProcessor,這裏針對多出接口說明一下:源碼分析

一、postProcessBeforeInstantiation調用時機爲bean實例化(Instantiation)以前 若是返回了bean實例, 則會替代原來正常經過target bean生成的bean的流程. 典型的例如aop返回proxy對象. 此時bean的執行流程將會縮短, 只會執行 post

 BeanPostProcessor#postProcessAfterInitialization接口完成初始化。

二、postProcessAfterInstantiation調用時機爲bean實例化(Instantiation)以後和任何初始化(Initialization)以前。

三、postProcessProperties調用時機爲postProcessAfterInstantiation執行以後並返回true, 返回的PropertyValues將做用於給定bean屬性賦值. spring 5.1以後出現以替換@Deprecated標註的postProcessPropertyValues

四、postProcessPropertyValues已經被標註@Deprecated,後續將會被postProcessProperties取代。

 

示例demo:

 1 public class InstantiationAwareBeanPostProcessorTest {  2     private ApplicationContext applicationContext ;  3 
 4  @Before  5     public void beforeApplicationContext(){  6         /**
 7  * ApplicationContext 自動註冊 BeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanFactoryPostProcessor  8  * 不須要手動註冊  9  * */
10         applicationContext = new ClassPathXmlApplicationContext("ioc-InstantiationAwareBeanPostProcessor.xml") ; 11  } 12 
13  @Test 14     public void test(){ 15         Bean bean = applicationContext.getBean("bean", Bean.class) ; 16  System.out.println(bean); 17  } 18 
19  @After 20     public void after(){ 21  ((ClassPathXmlApplicationContext)applicationContext).close(); 22  } 23 }
InstantiationAwareBeanPostProcessorTest.java
 1 public class LogicInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {  2 
 3  @Override  4     public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {  5         System.out.print("beanName:"+beanName+"執行..postProcessAfterInstantiation\n");  6         
 7         // 會影響postProcessProperties 是否執行,返回false不執行
 8         return true;  9  } 10 
11  @Override 12     public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { 13         System.out.print("beanName:"+beanName+"執行..postProcessBeforeInstantiation\n"); 14         if(beanClass == Bean.class){ 15 
16             //利用 其 生成動態代理
17             Enhancer enhancer = new Enhancer(); 18  enhancer.setSuperclass(beanClass); 19             enhancer.setCallback(new BeanMethodInterceptor()); 20             Bean bean = (Bean)enhancer.create(); 21             System.out.print("返回動態代理\n"); 22             return bean ; 23  } 24         return null ; 25  } 26 
27  @Override 28     public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { 29         System.out.print("beanName:"+beanName+"執行..postProcessProperties\n"); 30         return pvs; 31  } 32 
33     //************************************** BeanPostProcessor **********************************************
34 
35  @Override 36     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 37         System.out.print("beanName:"+beanName+"執行..postProcessAfterInitialization\n"); 38         return bean; 39  } 40 
41  @Override 42     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 43         System.out.print("beanName:"+beanName+"執行..postProcessBeforeInitialization\n"); 44         return bean; 45  } 46 }
LogicInstantiationAwareBeanPostProcessor.java
1 public class BeanMethodInterceptor implements MethodInterceptor { 2  @Override 3     public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 4         System.out.println("目標方法前:" + method+"\n"); 5         Object object = methodProxy.invokeSuper(o, objects); 6         System.out.println("目標方法後:" + method+"\n"); 7         return object; 8  } 9 }
BeanMethodInterceptor.java
 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:p="http://www.springframework.org/schema/p"
 4  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 5 
 6     <bean id="bean" class="com.nancy.ioc.Bean">
 7         <property name="name" value="zhouxiaoxing"/>
 8     </bean>
 9 
10     <bean id="logicInstantiationAwareBeanPostProcessor" class="com.nancy.ioc.InstantiationAwareBeanPostProcessor.LogicInstantiationAwareBeanPostProcessor"/>
11 
12 </beans>
ioc-InstantiationAwareBeanPostProcessor.xml
 1 public class Bean {  2     public Bean(){  3 
 4  }  5     public Bean(String name){  6         System.out.println("構造函數被調用啦");  7         this.name = name ;  8  }  9 
10     private String name ; 11 
12     public String getName() { 13         return name; 14  } 15 
16     public void setName(String name) { 17         this.name = name; 18  } 19 
20  @Override 21     public String toString() { 22         return "Bean{" +
23                 "name='" + name + '\'' +
24                 '}'; 25  } 26 }
Bean.java

 

運行結果以下:  因爲postProcessBeforeInstantiation經過cglib生成代理,  因此直接執行BeanPostProcessor#postProcessAfterInitialization接口完成初始化。bean生命週期縮短

beanName:bean執行..postProcessBeforeInstantiation 返回動態代理 beanName:bean執行..postProcessAfterInitialization 目標方法前:public java.lang.String com.nancy.ioc.Bean.toString() 目標方法後:public java.lang.String com.nancy.ioc.Bean.toString() Bean{name='null'}

 

 修改LogicInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation以下 :

 1  @Override  2     public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {  3         System.out.print("beanName:"+beanName+"執行..postProcessBeforeInstantiation\n");  4         return null ;  5  }  6 
 7  @Override  8     public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {  9         System.out.print("beanName:"+beanName+"執行..postProcessProperties\n"); 10 
11         if(bean instanceof Bean){ 12             //修改bean中name 的屬性值
13             PropertyValue value = pvs.getPropertyValue("name"); 14             System.out.print("修改以前 name 的value是:"+value.getValue()+"\n"); 15             value.setConvertedValue("我修改啦"); 16             return pvs; 17  } 18         return pvs; 19     }

 

運行結果以下:  因爲postProcessBeforeInstantiation返回null 並 postProcessAfterInstantiation返回true 因此執行會postProcessProperties。此時bean生命週期正常process

beanName:bean執行..postProcessBeforeInstantiation beanName:bean執行..postProcessAfterInstantiation beanName:bean執行..postProcessProperties 修改以前 name 的value是:TypedStringValue: value [zhouxiaoxing], target type [null] beanName:bean執行..postProcessBeforeInitialization beanName:bean執行..postProcessAfterInitialization Bean{name='我修改啦'}

 詳細demo示例能夠參考: https://gitee.com/zhouxiaoxing91/learning-src/tree/master

 

2、InstantiationAwareBeanPostProcessor與BeanPostProcessor對比

 一、BeanPostProcessor 執行時機爲bean初始化(Initialization)階段,平常能夠拓展該接口對bean初始化進行定製化處理。

 二、InstantiationAwareBeanPostProcessor 執行時機bean實例化(Instantiation)階段,典型用於替換bean默認建立方式,例如aop經過拓展接口生成代理對應,主要用於基礎框架層面。若是平常業務中須要拓展該,spring推薦使用適配器類InstantiationAwareBeanPostProcessorAdapter。

三、全部bean建立都會進行回調。

 

3、InstantiationAwareBeanPostProcessor源碼分析:註冊時機和觸發點

一、因爲InstantiationAwareBeanPostProcessor實質也是BeanPostProcessor接口,register時機是一致的,可參考:spring源碼分析系列 (2) spring拓展接口BeanPostProcessor 。

 

二、這裏着重分析接口觸發的時機,跟BeanPostProcessor同樣觸發入口從AbstractAutowireCapableBeanFactory#createBean開始 :

 1   /**
 2  * Central method of this class: creates a bean instance,  3  * populates the bean instance, applies post-processors, etc.  4  * @see #doCreateBean  5      */
 6  @Override  7     protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)  8             throws BeanCreationException {  9 
10         // 省略......
11 
12         try { 13             /**
14  * postProcessorsBeforeInstantiation 觸發入口 15              */ 
16             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
17             Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 18             if (bean != null) { 19                 return bean; 20  } 21  } 22         catch (Throwable ex) { 23             throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, 24                     "BeanPostProcessor before instantiation of bean failed", ex); 25  } 26 
27         try { 28             /**
29  * postProcessAfterInstantiation、postProcessProperties 觸發入口 30              */ 
31             Object beanInstance = doCreateBean(beanName, mbdToUse, args); 32             if (logger.isTraceEnabled()) { 33                 logger.trace("Finished creating instance of bean '" + beanName + "'"); 34  } 35             return beanInstance; 36  } 37         catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { 38             // A previously detected exception with proper bean creation context already, 39             // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
40             throw ex; 41  } 42         catch (Throwable ex) { 43             throw new BeanCreationException( 44                     mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); 45  } 46     }

 

2.一、跟進AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation, 分析postProcessorsBeforeInstantiation執行時機 :

 1   /**
 2  * Apply before-instantiation post-processors, resolving whether there is a  3  * before-instantiation shortcut for the specified bean.  4  * @param beanName the name of the bean  5  * @param mbd the bean definition for the bean  6  * @return the shortcut-determined bean instance, or {@code null} if none  7      */
 8  @Nullable  9     protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { 10         Object bean = null; 11         if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { 12             // Make sure bean class is actually resolved at this point.
13             if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { 14                 Class<?> targetType = determineTargetType(beanName, mbd); 15                 if (targetType != null) { 16                     /**
17  * 回調beanPostProcessorsBeforeInstantiation實例化,若是返回bean非null則直接執行 18  * beanPostProcessorsAfterInitialization進行實例初始化 19                      */ 
20                     bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); 21                     if (bean != null) { 22                         bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); 23  } 24  } 25  } 26             mbd.beforeInstantiationResolved = (bean != null); 27  } 28         return bean; 29  } 30 
31 
32     /**
33  * Apply InstantiationAwareBeanPostProcessors to the specified bean definition 34  * (by class and name), invoking their {@code postProcessBeforeInstantiation} methods. 35  * <p>Any returned object will be used as the bean instead of actually instantiating 36  * the target bean. A {@code null} return value from the post-processor will 37  * result in the target bean being instantiated. 38  * @param beanClass the class of the bean to be instantiated 39  * @param beanName the name of the bean 40  * @return the bean object to use instead of a default instance of the target bean, or {@code null} 41  * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 42      */
43  @Nullable 44     protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { 45         for (BeanPostProcessor bp : getBeanPostProcessors()) { 46             if (bp instanceof InstantiationAwareBeanPostProcessor) { 47                 /**
48  * 只要其中一個postProcessBeforeInstantiation返回實例bean即結束回調, 49  * 這個bean將會直接返回給bean容器管理 50                   */ 
51                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 52                 Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); 53                 if (result != null) { 54                     return result; 55  } 56  } 57  } 58         return null; 59  } 60 
61  @Override 62     public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) 63             throws BeansException { 64 
65         Object result = existingBean; 66         for (BeanPostProcessor processor : getBeanPostProcessors()) { 67             Object current = processor.postProcessAfterInitialization(result, beanName); 68             if (current == null) { 69                 return result; 70  } 71             result = current; 72  } 73         return result; 74     }

 

 二、跟進AbstractAutowireCapableBeanFactory#doCreateBean, 分析postProcessAfterInstantiation、postProcessProperties 執行時機 :

 1  /**
 2  * Actually create the specified bean. Pre-creation processing has already happened  3  * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.  4  * <p>Differentiates between default bean instantiation, use of a  5  * factory method, and autowiring a constructor.  6  * @param beanName the name of the bean  7  * @param mbd the merged bean definition for the bean  8  * @param args explicit arguments to use for constructor or factory method invocation  9  * @return a new instance of the bean 10  * @throws BeanCreationException if the bean could not be created 11  * @see #instantiateBean 12  * @see #instantiateUsingFactoryMethod 13  * @see #autowireConstructor 14    */
15   protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) 16       throws BeanCreationException { 17 
18     // 省略...... 19 
20     // Initialize the bean instance.
21     Object exposedObject = bean; 22     try { 23       /** 依據bean definition 完成bean屬性賦值 */ 
24  populateBean(beanName, mbd, instanceWrapper); 25       /** 執行bean初始化 */ 
26       exposedObject = initializeBean(beanName, exposedObject, mbd); 27  } 28     catch (Throwable ex) { 29       if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { 30         throw (BeanCreationException) ex; 31  } 32       else { 33         throw new BeanCreationException( 34             mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); 35  } 36  } 37 
38     // 省略......
39     
40     return exposedObject; 41   }

跟進AbstractAutowireCapableBeanFactory#populateBean
 1 /**
 2  * Populate the bean instance in the given BeanWrapper with the property values  3  * from the bean definition.  4  * @param beanName the name of the bean  5  * @param mbd the bean definition for the bean  6  * @param bw the BeanWrapper with bean instance  7      */
 8     @SuppressWarnings("deprecation")  // for postProcessPropertyValues
 9     protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {  10         if (bw == null) {  11             if (mbd.hasPropertyValues()) {  12                 throw new BeanCreationException(  13                         mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");  14  }  15             else {  16                 // Skip property population phase for null instance.
 17                 return;  18  }  19  }  20 
 21         // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the  22         // state of the bean before properties are set. This can be used, for example,  23         // to support styles of field injection.
 24         boolean continueWithPropertyPopulation = true;  25 
 26         /**
 27  * 知足兩個要求:  28  * 一、BeanDefinition爲應用程序bean,而非基礎框架bean信息。  29  * 二、註冊過InstantiationAwareBeanPostProcessor類型接口,上文有提到這個標誌位。  30  * 三、註冊了多個接口時,只要其中一個postProcessAfterInstantiation返回false,即中止後續執行。  31          */ 
 32         if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  33             for (BeanPostProcessor bp : getBeanPostProcessors()) {  34                 if (bp instanceof InstantiationAwareBeanPostProcessor) {  35                     InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  36                     if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {  37                         continueWithPropertyPopulation = false;  38                         break;  39  }  40  }  41  }  42  }  43 
 44         /**
 45  * 斷定是否執行如下流程,受到postProcessAfterInstantiation返回結果影響  46          */ 
 47         if (!continueWithPropertyPopulation) {  48             return;  49  }  50 
 51         PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);  52 
 53         /**
 54  * ioc依賴注入  55          */ 
 56         if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {  57             MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  58             // Add property values based on autowire by name if applicable.
 59             if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {  60  autowireByName(beanName, mbd, bw, newPvs);  61  }  62             // Add property values based on autowire by type if applicable.
 63             if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {  64  autowireByType(beanName, mbd, bw, newPvs);  65  }  66             pvs = newPvs;  67  }  68 
 69         /**
 70  * InstantiationAwareBeanPostProcessor標誌位 和 依賴注入檢查標誌位  71          */
 72         boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();  73         boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);  74 
 75         PropertyDescriptor[] filteredPds = null;  76         if (hasInstAwareBpps) {  77             if (pvs == null) {  78                 pvs = mbd.getPropertyValues();  79  }  80 
 81             /**
 82  * 一、優先回調postProcessProperties. spring-5.1以後新增回調接口  83  * 二、再回調postProcessPropertyValues,一旦返回null即結束. spring-5.1以前邏輯  84               */
 85             for (BeanPostProcessor bp : getBeanPostProcessors()) {  86                 if (bp instanceof InstantiationAwareBeanPostProcessor) {  87                     InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  88                     PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);  89                     if (pvsToUse == null) {  90                         if (filteredPds == null) {  91                             filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);  92  }  93                         pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);  94                         if (pvsToUse == null) {  95                             return;  96  }  97  }  98                     pvs = pvsToUse;  99  } 100  } 101  } 102 
103         /**
104  * 依賴注入校驗 105          */
106         if (needsDepCheck) { 107             if (filteredPds == null) { 108                 filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); 109  } 110  checkDependencies(beanName, mbd, filteredPds, pvs); 111  } 112 
113         /**
114  * 此時會將上述處理後的PropertyValues應用於bean屬性 115          */
116         if (pvs != null) { 117  applyPropertyValues(beanName, mbd, bw, pvs); 118  } 119     }
 

總結一下:

  • InstantiationAwareBeanPostProcessor的觸發入口從AbstractAutowireCapableBeanFactory#createBean開始。
  • bean實例化以前會檢測是否存在該類型的接口,並觸發前置postProcessBeforeInstantiation。註冊多個實例時會依次執行回調,任何一個返回非null則直接執行BeanPostProcessor#postProcessAfterInitialization完成初始化。返回的bean直接返回容器,生命週期縮短。
  • 後置postProcessAfterInstantiation會在實例化以後,依賴注入和初始化方法以前。註冊多個接口只要其中一個返回false,即中止後續執行。 返回結果會影響後續執行流程,經過此定製化bean屬性注入等操做。
  • 優先回調postProcessProperties,spring-5.1以後新增回調接口 用以替代標註過期的postProcessPropertyValues方法。
  • InstantiationAwareBeanPostProcessor設計主要給基礎性框架使用,平常應用spring推薦使用適配器類InstantiationAwareBeanPostProcessorAdapter。
相關文章
相關標籤/搜索