spring源码分析系列 (3) spring拓展接口InstantiationAwareBeanPostProcessor
主要分析内容:
一、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:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
二、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。