`

Spring的BeanFactoryPostProcessor和BeanPostProcessor

 
阅读更多

http://blog.csdn.net/caihaijiang/article/details/35552859

 

BeanFactoryPostProcessor和BeanPostProcessor,这两个接口,都是Spring初始化bean时对外暴露的扩展点。两个接口名称看起来很相似,但作用及使用场景却不同,分析如下:

1、BeanFactoryPostProcessor接口

该接口的定义如下:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public interface BeanFactoryPostProcessor {  
  2.   
  3.     /** 
  4.      * Modify the application context's internal bean factory after its standard 
  5.      * initialization. All bean definitions will have been loaded, but no beans 
  6.      * will have been instantiated yet. This allows for overriding or adding 
  7.      * properties even to eager-initializing beans. 
  8.      * @param beanFactory the bean factory used by the application context 
  9.      * @throws org.springframework.beans.BeansException in case of errors 
  10.      */  
  11.     void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;  
  12.   
  13. }  

实现该接口,可以在spring的bean创建之前,修改bean的定义属性。也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。
注意:BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的。接口方法的入参是ConfigurrableListableBeanFactory,使用该参数,可以获取到相关bean的定义信息,例子:

 

1)spring bean的定义:

 

[html] view plaincopy在CODE上查看代码片派生到我的代码片
 
  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:context="http://www.springframework.org/schema/context"  
  4.     xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"  
  5.     xmlns:aop="http://www.springframework.org/schema/aop"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  7.                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd  
  8.                 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"  
  9.     default-autowire="byName">  
  10.       
  11.     <bean id="myJavaBean" class="com.ali.caihj.postprocessor.MyJavaBean">  
  12.         <property name="desc" value="测试一下啦" />  
  13.         <property name="remark" value="这是备注信息啦啦啦" />  
  14.     </bean>  
  15.     <bean id="myBeanFactoryPostProcessor" class="com.ali.caihj.postprocessor.MyBeanFactoryPostProcessor" />  
  16. </beans>  

 

2)自定义的BeanFactoryPostProcessor:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {  
  2.   
  3.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {  
  4.         System.out.println("调用MyBeanFactoryPostProcessor的postProcessBeanFactory");  
  5.         BeanDefinition bd = beanFactory.getBeanDefinition("myJavaBean");  
  6.         System.out.println("属性值============" + bd.getPropertyValues().toString());  
  7.         MutablePropertyValues pv =  bd.getPropertyValues();    
  8.         if (pv.contains("remark")) {    
  9.             pv.addPropertyValue("remark""把备注信息修改一下");    
  10.         }    
  11.         bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);  
  12.     }  
  13.   
  14. }  

spring中,有内置的一些BeanFactoryPostProcessor实现类,常用的有:

  • org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
  • org.springframework.beans.factory.config.PropertyOverrideConfigurer
  • org.springframework.beans.factory.config.CustomEditorConfigurer:用来注册自定义的属性编辑器

 

2、BeanPostProcessor接口

该接口的定义如下:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public interface BeanPostProcessor {  
  2.   
  3.     /** 
  4.      * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean 
  5.      * initialization callbacks (like InitializingBean's <code>afterPropertiesSet</code> 
  6.      * or a custom init-method). The bean will already be populated with property values. 
  7.      * The returned bean instance may be a wrapper around the original. 
  8.      * @param bean the new bean instance 
  9.      * @param beanName the name of the bean 
  10.      * @return the bean instance to use, either the original or a wrapped one 
  11.      * @throws org.springframework.beans.BeansException in case of errors 
  12.      * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet 
  13.      */  
  14.     Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;  
  15.   
  16.     /** 
  17.      * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean 
  18.      * initialization callbacks (like InitializingBean's <code>afterPropertiesSet</code> 
  19.      * or a custom init-method). The bean will already be populated with property values. 
  20.      * The returned bean instance may be a wrapper around the original. 
  21.      * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean 
  22.      * instance and the objects created by the FactoryBean (as of Spring 2.0). The 
  23.      * post-processor can decide whether to apply to either the FactoryBean or created 
  24.      * objects or both through corresponding <code>bean instanceof FactoryBean</code> checks. 
  25.      * <p>This callback will also be invoked after a short-circuiting triggered by a 
  26.      * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, 
  27.      * in contrast to all other BeanPostProcessor callbacks. 
  28.      * @param bean the new bean instance 
  29.      * @param beanName the name of the bean 
  30.      * @return the bean instance to use, either the original or a wrapped one 
  31.      * @throws org.springframework.beans.BeansException in case of errors 
  32.      * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet 
  33.      * @see org.springframework.beans.factory.FactoryBean 
  34.      */  
  35.     Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;  
  36.   
  37. }  

BeanPostProcessor,可以在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。这里说的初始化方法,指的是下面两种:

 

1)bean实现了InitializingBean接口,对应的方法为afterPropertiesSet

2)在bean定义的时候,通过init-method设置的方法

注意:BeanPostProcessor是在spring容器加载了bean的定义文件并且实例化bean之后执行的。BeanPostProcessor的执行顺序是在BeanFactoryPostProcessor之后。

spring中,有内置的一些BeanPostProcessor实现类,例如:

  • org.springframework.context.annotation.CommonAnnotationBeanPostProcessor:支持@Resource注解的注入
  • org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor:支持@Required注解的注入
  • org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor:支持@Autowired注解的注入
  • org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor:支持@PersistenceUnit和@PersistenceContext注解的注入
  • org.springframework.context.support.ApplicationContextAwareProcessor:用来为bean注入ApplicationContext等容器对象

这些注解类的BeanPostProcessor,在spring配置文件中,可以通过这样的配置 <context:component-scan base-package="*.*" /> ,自动进行注册。(spring通过ComponentScanBeanDefinitionParser类来解析该标签

 

3、下面通过完整的一个例子,来加深理解

1)定义一个JavaBean

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public class MyJavaBean implements InitializingBean {  
  2.     private String desc;  
  3.     private String remark;  
  4.       
  5.     public MyJavaBean() {  
  6.         System.out.println("MyJavaBean的构造函数被执行啦");  
  7.     }  
  8.     public String getDesc() {  
  9.         return desc;  
  10.     }  
  11.     public void setDesc(String desc) {  
  12.         System.out.println("调用setDesc方法");  
  13.         this.desc = desc;  
  14.     }  
  15.     public String getRemark() {  
  16.         return remark;  
  17.     }  
  18.     public void setRemark(String remark) {  
  19.         System.out.println("调用setRemark方法");  
  20.         this.remark = remark;  
  21.     }  
  22.     public void afterPropertiesSet() throws Exception {  
  23.         System.out.println("调用afterPropertiesSet方法");  
  24.         this.desc = "在初始化方法中修改之后的描述信息";  
  25.     }  
  26.     public void initMethod() {  
  27.         System.out.println("调用initMethod方法");  
  28.     }  
  29.     public String toString() {  
  30.         StringBuilder builder = new StringBuilder();  
  31.         builder.append("[描述:").append(desc);  
  32.         builder.append(", 备注:").append(remark).append("]");  
  33.         return builder.toString();  
  34.     }  
  35. }  

 


2)定义一个BeanFactoryPostProcessor

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {  
  2.   
  3.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {  
  4.         System.out.println("调用MyBeanFactoryPostProcessor的postProcessBeanFactory");  
  5.         BeanDefinition bd = beanFactory.getBeanDefinition("myJavaBean");  
  6.         MutablePropertyValues pv =  bd.getPropertyValues();    
  7.         if (pv.contains("remark")) {    
  8.             pv.addPropertyValue("remark""在BeanFactoryPostProcessor中修改之后的备忘信息");    
  9.         }    
  10.     }  
  11.   
  12. }  

3)定义一个BeanPostProcessor

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public class MyBeanPostProcessor implements BeanPostProcessor {  
  2.   
  3.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
  4.         System.out.println("BeanPostProcessor,对象" + beanName + "调用初始化方法之前的数据: " + bean.toString());  
  5.         return bean;  
  6.     }  
  7.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  8.         System.out.println("BeanPostProcessor,对象" + beanName + "调用初始化方法之后的数据:" + bean.toString());  
  9.         return bean;  
  10.     }  
  11. }  

4)spring的配置

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  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:context="http://www.springframework.org/schema/context"  
  4.     xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"  
  5.     xmlns:aop="http://www.springframework.org/schema/aop"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  7.                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd  
  8.                 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"  
  9.     default-autowire="byName">  
  10.       
  11.     <bean id="myJavaBean" class="com.ali.caihj.postprocessor.MyJavaBean" init-method="initMethod">  
  12.         <property name="desc" value="原始的描述信息" />  
  13.         <property name="remark" value="原始的备注信息" />  
  14.     </bean>  
  15.       
  16.     <bean id="myBeanPostProcessor" class="com.ali.caihj.postprocessor.MyBeanPostProcessor" />  
  17.     <bean id="myBeanFactoryPostProcessor" class="com.ali.caihj.postprocessor.MyBeanFactoryPostProcessor" />  
  18. </beans>  

5)测试类

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public class PostProcessorMain {  
  2.     public static void main(String[] args) {  
  3.         ApplicationContext context = new ClassPathXmlApplicationContext("config/postprocessor.xml");  
  4.         MyJavaBean bean = (MyJavaBean) context.getBean("myJavaBean");  
  5.         System.out.println("===============下面输出结果============");  
  6.         System.out.println("描述:" + bean.getDesc());  
  7.         System.out.println("备注:" + bean.getRemark());  
  8.   
  9.     }  
  10. }  

6)运行结果如下:

 

7)分析

从上面的结果可以看出,BeanFactoryPostProcessor在bean实例化之前执行,之后实例化bean(调用构造函数,并调用set方法注入属性值),然后在调用两个初始化方法前后,执行了BeanPostProcessor。初始化方法的执行顺序是,先执行afterPropertiesSet,再执行init-method。

 

4、进一步深入分析

在使用ApplicationContext启动spring容器的时候,在AbstractApplicationContext.refresh()方法中,完成相关初始化工作:

1)BeanFactoryPostProcessor.postProcessBeanFactory,是在第5步执行的,invokeBeanFactoryPostProcessors方法实现如下:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. /** 
  2.      * Instantiate and invoke all registered BeanFactoryPostProcessor beans, 
  3.      * respecting explicit order if given. 
  4.      * <p>Must be called before singleton instantiation. 
  5.      */  
  6.     protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {  
  7.         // Invoke factory processors registered with the context instance.  
  8.         for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {  
  9.             BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();  
  10.             factoryProcessor.postProcessBeanFactory(beanFactory);  
  11.         }  
  12.   
  13.         // Do not initialize FactoryBeans here: We need to leave all regular beans  
  14.         // uninitialized to let the bean factory post-processors apply to them!  
  15.         String[] postProcessorNames =  
  16.                 beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.classtruefalse);  
  17.   
  18.         // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,  
  19.         // Ordered, and the rest.  
  20.         List priorityOrderedPostProcessors = new ArrayList();  
  21.         List orderedPostProcessorNames = new ArrayList();  
  22.         List nonOrderedPostProcessorNames = new ArrayList();  
  23.         for (int i = 0; i < postProcessorNames.length; i++) {  
  24.             if (isTypeMatch(postProcessorNames[i], PriorityOrdered.class)) {  
  25.                 priorityOrderedPostProcessors.add(beanFactory.getBean(postProcessorNames[i]));  
  26.             }  
  27.             else if (isTypeMatch(postProcessorNames[i], Ordered.class)) {  
  28.                 orderedPostProcessorNames.add(postProcessorNames[i]);  
  29.             }  
  30.             else {  
  31.                 nonOrderedPostProcessorNames.add(postProcessorNames[i]);  
  32.             }  
  33.         }  
  34.   
  35.         // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.  
  36.         Collections.sort(priorityOrderedPostProcessors, new OrderComparator());  
  37.         invokeBeanFactoryPostProcessors(beanFactory, priorityOrderedPostProcessors);  
  38.   
  39.         // Next, invoke the BeanFactoryPostProcessors that implement Ordered.  
  40.         List orderedPostProcessors = new ArrayList();  
  41.         for (Iterator it = orderedPostProcessorNames.iterator(); it.hasNext();) {  
  42.             String postProcessorName = (String) it.next();  
  43.             orderedPostProcessors.add(getBean(postProcessorName));  
  44.         }  
  45.         Collections.sort(orderedPostProcessors, new OrderComparator());  
  46.         invokeBeanFactoryPostProcessors(beanFactory, orderedPostProcessors);  
  47.   
  48.         // Finally, invoke all other BeanFactoryPostProcessors.  
  49.         List nonOrderedPostProcessors = new ArrayList();  
  50.         for (Iterator it = nonOrderedPostProcessorNames.iterator(); it.hasNext();) {  
  51.             String postProcessorName = (String) it.next();  
  52.             nonOrderedPostProcessors.add(getBean(postProcessorName));  
  53.         }  
  54.         invokeBeanFactoryPostProcessors(beanFactory, nonOrderedPostProcessors);  
  55.     }  
  56.   
  57.     /** 
  58.      * Invoke the given BeanFactoryPostProcessor beans. 
  59.      */  
  60.     private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List postProcessors) {  
  61.         for (Iterator it = postProcessors.iterator(); it.hasNext();) {  
  62.             BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor) it.next();  
  63.             postProcessor.postProcessBeanFactory(beanFactory);  
  64.         }  
  65.     }  

通过beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false),获取spring配置文件中定义的所有实现BeanFactoryPostProcessor接口的bean,然后根据优先级进行排序,之后对于每个BeanFactoryPostProcessor,调用postProcessBeanFactory方法。

 

2)而BeanPostProcessor的执行,取决于配置文件中bean的定义,如果定义的bean是singleton并且不是抽象类,也不延迟初始化,则BeanPostProcessor是在第11步中执行;而对于prototype的bean,BeanPostProcessor是在程序getBean的时候执行的。在第6步中,调用registerBeanPostProcessors方法,注册所有实现BeanPostProcessor接口的bean,该方法的实现如下:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {  
  2.         String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.classtruefalse);  
  3.   
  4.         // Register BeanPostProcessorChecker that logs an info message when  
  5.         // a bean is created during BeanPostProcessor instantiation, i.e. when  
  6.         // a bean is not eligible for getting processed by all BeanPostProcessors.  
  7.         int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;  
  8.         beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));  
  9.   
  10.         // Separate between BeanPostProcessors that implement PriorityOrdered,  
  11.         // Ordered, and the rest.  
  12.         List priorityOrderedPostProcessors = new ArrayList();  
  13.         List orderedPostProcessorNames = new ArrayList();  
  14.         List nonOrderedPostProcessorNames = new ArrayList();  
  15.         for (int i = 0; i < postProcessorNames.length; i++) {  
  16.             if (isTypeMatch(postProcessorNames[i], PriorityOrdered.class)) {  
  17.                 priorityOrderedPostProcessors.add(beanFactory.getBean(postProcessorNames[i]));  
  18.             }  
  19.             else if (isTypeMatch(postProcessorNames[i], Ordered.class)) {  
  20.                 orderedPostProcessorNames.add(postProcessorNames[i]);  
  21.             }  
  22.             else {  
  23.                 nonOrderedPostProcessorNames.add(postProcessorNames[i]);  
  24.             }  
  25.         }  
  26.   
  27.         // First, register the BeanPostProcessors that implement PriorityOrdered.  
  28.         Collections.sort(priorityOrderedPostProcessors, new OrderComparator());  
  29.         registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);  
  30.   
  31.         // Next, register the BeanPostProcessors that implement Ordered.  
  32.         List orderedPostProcessors = new ArrayList();  
  33.         for (Iterator it = orderedPostProcessorNames.iterator(); it.hasNext();) {  
  34.             String postProcessorName = (String) it.next();  
  35.             orderedPostProcessors.add(getBean(postProcessorName));  
  36.         }  
  37.         Collections.sort(orderedPostProcessors, new OrderComparator());  
  38.         registerBeanPostProcessors(beanFactory, orderedPostProcessors);  
  39.   
  40.         // Finally, register all other BeanPostProcessors.  
  41.         List nonOrderedPostProcessors = new ArrayList();  
  42.         for (Iterator it = nonOrderedPostProcessorNames.iterator(); it.hasNext();) {  
  43.             String postProcessorName = (String) it.next();  
  44.             nonOrderedPostProcessors.add(getBean(postProcessorName));  
  45.         }  
  46.         registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);  
  47.     }  

 

在第11步中,调用finishBeanFactoryInitialization方法,该方法通过调用DefaultListableBeanFactory.preInstantiateSingletons(),进行相关初始化工作:

从上面的代码可以看出,对于非抽象类、非延迟初始化的单例bean,在spring容器启动的时候调用getBean方法来实例化bean,并进行相关初始化工作,getBean方法最终调用AbstractAutowireCapableBeanFactory.doCreateBean方法,该方法的实现如下:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {  
  2.         // Instantiate the bean.  
  3.         BeanWrapper instanceWrapper = null;  
  4.         if (mbd.isSingleton()) {  
  5.             instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);  
  6.         }  
  7.         if (instanceWrapper == null) {  
  8.             instanceWrapper = createBeanInstance(beanName, mbd, args);  
  9.         }  
  10.         final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);  
  11.         Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);  
  12.   
  13.         // Allow post-processors to modify the merged bean definition.  
  14.         synchronized (mbd.postProcessingLock) {  
  15.             if (!mbd.postProcessed) {  
  16.                 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);  
  17.                 mbd.postProcessed = true;  
  18.             }  
  19.         }  
  20.   
  21.         // Eagerly cache singletons to be able to resolve circular references  
  22.         // even when triggered by lifecycle interfaces like BeanFactoryAware.  
  23.         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&  
  24.                 isSingletonCurrentlyInCreation(beanName));  
  25.         if (earlySingletonExposure) {  
  26.             if (logger.isDebugEnabled()) {  
  27.                 logger.debug("Eagerly caching bean '" + beanName +  
  28.                         "' to allow for resolving potential circular references");  
  29.             }  
  30.             addSingletonFactory(beanName, new ObjectFactory() {  
  31.                 public Object getObject() throws BeansException {  
  32.                     return getEarlyBeanReference(beanName, mbd, bean);  
  33.                 }  
  34.             });  
  35.         }  
  36.   
  37.         // Initialize the bean instance.  
  38.         Object exposedObject = bean;  
  39.         try {  
  40.             populateBean(beanName, mbd, instanceWrapper);  
  41.             exposedObject = initializeBean(beanName, exposedObject, mbd);  
  42.         }  
  43.         catch (Throwable ex) {  
  44.             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {  
  45.                 throw (BeanCreationException) ex;  
  46.             }  
  47.             else {  
  48.                 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);  
  49.             }  
  50.         }  
  51.   
  52.         if (earlySingletonExposure) {  
  53.             Object earlySingletonReference = getSingleton(beanName, false);  
  54.             if (earlySingletonReference != null) {  
  55.                 if (exposedObject == bean) {  
  56.                     exposedObject = earlySingletonReference;  
  57.                 }  
  58.                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {  
  59.                     String[] dependentBeans = getDependentBeans(beanName);  
  60.                     Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);  
  61.                     for (int i = 0; i < dependentBeans.length; i++) {  
  62.                         String dependentBean = dependentBeans[i];  
  63.                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {  
  64.                             actualDependentBeans.add(dependentBean);  
  65.                         }  
  66.                     }  
  67.                     if (!actualDependentBeans.isEmpty()) {  
  68.                         throw new BeanCurrentlyInCreationException(beanName,  
  69.                                 "Bean with name '" + beanName + "' has been injected into other beans [" +  
  70.                                 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +  
  71.                                 "] in its raw version as part of a circular reference, but has eventually been " +  
  72.                                 "wrapped. This means that said other beans do not use the final version of the " +  
  73.                                 "bean. This is often the result of over-eager type matching - consider using " +  
  74.                                 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");  
  75.                     }  
  76.                 }  
  77.             }  
  78.         }  
  79.   
  80.         // Register bean as disposable.  
  81.         registerDisposableBeanIfNecessary(beanName, bean, mbd);  
  82.   
  83.         return exposedObject;  
  84.     }  

在该方法中,首先调用createBeanInstance方法,创建bean实例对象(这个时候执行bean的构造方法),然后调用populateBean方法,对bean进行填充,注入相关依赖,之后再调用方法initializeBean,进行相关初始化工作,initializeBean方法的实现如下:

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {  
  2.         if (bean instanceof BeanNameAware) {  
  3.             ((BeanNameAware) bean).setBeanName(beanName);  
  4.         }  
  5.   
  6.         if (bean instanceof BeanClassLoaderAware) {  
  7.             ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());  
  8.         }  
  9.   
  10.         if (bean instanceof BeanFactoryAware) {  
  11.             ((BeanFactoryAware) bean).setBeanFactory(this);  
  12.         }  
  13.   
  14.         Object wrappedBean = bean;  
  15.         if (mbd == null || !mbd.isSynthetic()) {  
  16.             wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  
  17.         }  
  18.   
  19.         try {  
  20.             invokeInitMethods(beanName, wrappedBean, mbd);  
  21.         }  
  22.         catch (Throwable ex) {  
  23.             throw new BeanCreationException(  
  24.                     (mbd != null ? mbd.getResourceDescription() : null),  
  25.                     beanName, "Invocation of init method failed", ex);  
  26.         }  
  27.   
  28.         if (mbd == null || !mbd.isSynthetic()) {  
  29.             wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);  
  30.         }  
  31.         return wrappedBean;  
  32.     }  

从上面的实现可以看出,先调用applyBeanPostProcessorsBeforeInitialization方法,执行每个BeanPostProcessor的postProcessBeforeInitialization,然后调用invokeInitMethods方法,执行bean的初始化方法,最后调用applyBeanPostProcessorsAfterInitialization方法,执行每个BeanPostProcessor的postProcessAfterInitialization方法。这三个方法的实现如下:

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1.     public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)  
  2.             throws BeansException {  
  3.   
  4.         Object result = existingBean;  
  5.         for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {  
  6.             BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();  
  7.             result = beanProcessor.postProcessBeforeInitialization(result, beanName);  
  8.         }  
  9.         return result;  
  10.     }  
  11.   
  12.     public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)  
  13.             throws BeansException {  
  14.   
  15.         Object result = existingBean;  
  16.         for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {  
  17.             BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();  
  18.             result = beanProcessor.postProcessAfterInitialization(result, beanName);  
  19.         }  
  20.         return result;  
  21.     }  
  22. protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)  
  23.             throws Throwable {  
  24.   
  25.         boolean isInitializingBean = (bean instanceof InitializingBean);  
  26.         if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {  
  27.             if (logger.isDebugEnabled()) {  
  28.                 logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");  
  29.             }  
  30.             ((InitializingBean) bean).afterPropertiesSet();  
  31.         }  
  32.   
  33.         String initMethodName = (mbd != null ? mbd.getInitMethodName() : null);  
  34.         if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&  
  35.                 !mbd.isExternallyManagedInitMethod(initMethodName)) {  
  36.             invokeCustomInitMethod(beanName, bean, initMethodName, mbd.isEnforceInitMethod());  
  37.         }  
  38.     }  

从invokeInitMethods方法的实现可以看出,先执行afterPropertiesSet方法,然后再通过反射,执行init-method指定的方法。

分享到:
评论

相关推荐

    com-spring-ioc-demo:源码主要是学习Spring IOC的原理,以及对Bean的注册及控制,主要运用以下类对Spring进行扩展学习:BeanPostProcessor,BeanFactoryAware,BeanNameAware,ApplicationContextAware,FactoryBean,BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor,BeanPostProcessor,ResourceLoaderA

    BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor,BeanPostProcessor,ResourceLoaderAware,InvocationHandler。 BeanPostProcessor接口的实现类如何被注册到Spring容器2.更改bean的定义...

    spring培训.pptx

    了解spring的加载机制 beanPostProcessor,beanFactoryPostProcessor 的使用 springmvc 的父子容器 aop切面说明 公司内部培训课件

    Spring-Reference_zh_CN(Spring中文参考手册)

    6.1.2. Spring AOP的功能和目标 6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点(pointcut) 6.2.3.1. 切入点指定者的支持 6.2.3.2. 合并切入点...

    开源框架 Spring Gossip

    不使用XML定义档进行 Bean设置 Aware 相关介面 BeanPostProcessor BeanFactoryPostProcessor PropertyPlaceholderConfigurer PropertyOverrideConfigurer CustomEditorConfigurer ...

    Spring 2.0 开发参考手册

    6.1.2. Spring AOP的功能和目标 6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点(pointcut) 6.2.4. 声明通知 6.2.5. 引入(Introductions)...

    Spring中文帮助文档

    6.1.2. Spring AOP的功能和目标 6.1.3. AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点(pointcut) 6.2.4. 声明通知 6.2.5. 引入(Introduction) 6.2.6. ...

    spring chm文档

    6.1.2. Spring AOP的功能和目标 6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点(pointcut) 6.2.4. 声明通知 6.2.5. 引入(Introductions)...

    Spring API

    2. Spring 2.0和 2.5的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 新的bean作用域 2.2.2. 更简单的XML配置 2.2.3. 可扩展的XML编写 2.2.4. Annotation(注解)驱动配置 2.2.5. 在classpath中自动搜索组件...

    Spring 3 Reference中文

    1.3.1.1 Spring 依赖和基于Spring 13 1.3.1.2 Maven 依赖管理. 14 1.3.1.3 Ivy 依赖管理 15 1.3.2 日志. 16 1.3.2.1 不使用Commons Logging .. 17 1.3.2.2 使用SLF4J 17 1.3.2.3 ...

    通俗易懂的Spring注解驱动开发教程(含配套资料)

    后置处理器(BeanPostProcessor.BeanFactoryPostProcessor等) 2).监听器(ApplicationListener) 3).Spring容器启动过程; 3).web原理 1).Servlet3.0标准新增特性 2).异步请求相关 本视频使用了maven...

    SPRING API 2.0.CHM

    BeanFactoryPostProcessor BeanFactoryReference BeanFactoryRefreshableTargetSource BeanFactoryUtils BeanInitializationException BeanInstantiationException BeanIsAbstractException ...

    spring3.1中文参考文档

    1.3.1.1 Spring依赖和基于Spring ................................................................................................... 14 1.3.1.2 Maven依赖管理 ...............................................

    动力节点SSM课件源码分析教程配套资料分享

    什么是BeanPostProcessor,什么是BeanFactoryPostProcessor?Service中注入的Mapper接口是什么对象?Spring Bean的生命周期,Spring循环依赖等等问题。课程讲解细致,一行一行带你读懂代码,一行一行调试源码,彻...

    spring-framework-reference-4.1.2

    3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................

    ZhiShan-zh.github.io:互联网开发工程师知识笔记

    开发笔记 1 Java 1.1 Java 关键字解释:▣ ...Spring高级:后处理bean的接口BeanPostProcessor和BeanFactoryPostProcessor SpringMVC基础:SpringMVC入门▣SpringMVC架构▣SpringMVC参数的传递 Spr

    spring-framework-reference4.1.4

    3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................

Global site tag (gtag.js) - Google Analytics