主要分析內容: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 }
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 }
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 }
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>
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 }
運行結果以下: 因爲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 }
總結一下: