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


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

 

主要分析內容:

一、InstantiationAwareBeanPostProcessor簡述與demo示例

二、InstantiationAwareBeanPostProcessor與BeanPostProcessor對比

三、InstantiationAwareBeanPostProcessor源碼分析:注冊時機和觸發點

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

 

一、InstantiationAwareBeanPostProcessor簡述與demo示例

 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,這里針對多出接口說明一下:

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

 BeanPostProcessor#postProcessAfterInitialization接口完成初始化。

2、postProcessAfterInstantiation調用時機為bean實例化(Instantiation)之后和任何初始化(Initialization)之前。

3、postProcessProperties調用時機為postProcessAfterInstantiation執行之后並返回true, 返回的PropertyValues將作用於給定bean屬性賦值. spring 5.1之后出現以替換@Deprecated標注的postProcessPropertyValues

4、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

 

二、InstantiationAwareBeanPostProcessor與BeanPostProcessor對比

 1、BeanPostProcessor 執行時機為bean初始化(Initialization)階段,日常可以拓展該接口對bean初始化進行定制化處理。

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

3、所有bean創建都會進行回調。

 

三、InstantiationAwareBeanPostProcessor源碼分析:注冊時機和觸發點

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

 

2、這里着重分析接口觸發的時機,跟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.1、跟進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     }

 

 2、跟進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          * 1、BeanDefinition為應用程序bean,而非基礎框架bean信息。  29          * 2、注冊過InstantiationAwareBeanPostProcessor類型接口,上文有提到這個標志位。  30          * 3、注冊了多個接口時,只要其中一個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               * 1、優先回調postProcessProperties. spring-5.1之后新增回調接口  83               * 2、再回調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。

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM