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。

 

 

 

 

 

 

posted on 2019-01-19 16:57  小猩  阅读(6374)  评论(1编辑  收藏  举报

导航