1. 程式人生 > >Spring生命週期之BeanFactoryPostPorcessor和BeanPostProcessor

Spring生命週期之BeanFactoryPostPorcessor和BeanPostProcessor

BeanFactoryPostProcessor和BeanPostProcessor,這兩個介面,都是Spring初始化bean時對外暴露的擴充套件點。

1、BeanFactoryPostProcessor介面

該介面的定義如下:

  1. publicinterface BeanFactoryPostProcessor {  
  2.     /** 
  3.      * Modify the application context's internal bean factory after its standard 
  4.      * initialization. All bean definitions will have been loaded, but no beans
     
  5.      * will have been instantiated yet. This allows for overriding or adding 
  6.      * properties even to eager-initializing beans. 
  7.      * @param beanFactory the bean factory used by the application context 
  8.      * @throws org.springframework.beans.BeansException in case of errors 
  9.      */
  10.     void
     postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;  
  11. }  
實現該介面,可以在spring的bean建立之前,修改bean的定義屬性。也就是說,Spring允許BeanFactoryPostProcessor在容器例項化任何其它bean之前讀取配置元資料,並可以根據需要進行修改,例如可以把bean的scope從singleton改為prototype,也可以把property的值給修改掉。可以同時配置多個BeanFactoryPostProcessor,並通過設定'order'屬性來控制各個BeanFactoryPostProcessor的執行次序。

自定義的BeanFactoryPostProcessor:

  1. publicclass MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {  
  2.     publicvoid postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {  
  3.         System.out.println("呼叫MyBeanFactoryPostProcessor的postProcessBeanFactory");  
  4.         BeanDefinition bd = beanFactory.getBeanDefinition("myJavaBean");  
  5.         System.out.println("屬性值============" + bd.getPropertyValues().toString());  
  6.         MutablePropertyValues pv =  bd.getPropertyValues();    
  7.         if (pv.contains("remark")) {    
  8.             pv.addPropertyValue("remark""把備註資訊修改一下");    
  9.         }    
  10.         bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);  
  11.     }  
  12. }  
spring中,有內建的一些BeanFactoryPostProcessor實現類,常用的有:
  • org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
  • org.springframework.beans.factory.config.PropertyOverrideConfigurer
  • org.springframework.beans.factory.config.CustomEditorConfigurer:用來註冊自定義的屬性編輯器

2、BeanPostProcessor介面

該介面的定義如下:

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

在使用ApplicationContext啟動spring容器的時候,在AbstractApplicationContext.refresh()方法中,完成相關初始化工作:


1)BeanFactoryPostProcessor.postProcessBeanFactory,是在第5步執行的,invokeBeanFactoryPostProcessors方法實現如下:

  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.     protectedvoid 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.         // Do not initialize FactoryBeans here: We need to leave all regular beans
  13.         // uninitialized to let the bean factory post-processors apply to them!
  14.         String[] postProcessorNames =  
  15.                 beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.classtruefalse);  
  16.         // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
  17.         // Ordered, and the rest.
  18.         List priorityOrderedPostProcessors = new ArrayList();  
  19.         List orderedPostProcessorNames = new ArrayList();  
  20.         List nonOrderedPostProcessorNames = new ArrayList();  
  21.         for (int i = 0; i < postProcessorNames.length; i++) {  
  22.             if (isTypeMatch(postProcessorNames[i], PriorityOrdered.class)) {  
  23.                 priorityOrderedPostProcessors.add(beanFactory.getBean(postProcessorNames[i]));  
  24.             }  
  25.             elseif (isTypeMatch(postProcessorNames[i], Ordered.class)) {  
  26.                 orderedPostProcessorNames.add(postProcessorNames[i]);  
  27.             }  
  28.             else {  
  29.                 nonOrderedPostProcessorNames.add(postProcessorNames[i]);  
  30.             }  
  31.         }  
  32.         // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
  33.         Collections.sort(priorityOrderedPostProcessors, new OrderComparator());  
  34.         invokeBeanFactoryPostProcessors(beanFactory, priorityOrderedPostProcessors);  
  35.         // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
  36.         List orderedPostProcessors = new ArrayList();  
  37.         for (Iterator it = orderedPostProcessorNames.iterator(); it.hasNext();) {  
  38.             String postProcessorName = (String) it.next();  
  39.             orderedPostProcessors.add(getBean(postProcessorName));  
  40.         }  
  41.         Collections.sort(orderedPostProcessors, new OrderComparator());  
  42. 相關推薦

    Spring生命週期BeanFactoryPostPorcessorBeanPostProcessor

    BeanFactoryPostProcessor和BeanPostProcessor,這兩個介面,都是Spring初始化bean時對外暴露的擴充套件點。 1、BeanFactoryPostProcessor介面 該介面的定義如下: p

    spring-bean生命週期初始化銷燬的三種方式

    1,註解bean之指定init-method/destroy-method 這種方式spring註解之@Bean註解,這邊再簡單演示如下: 配置類中增加一個bean如下: /** * 定義一個bean物件 * @return */

    Spring Bean的生命週期我的理解(三)------BeanFactoryFactoryBean

    前言 大家可能使用Spring框架已經很久了,但是對其中的一些概念可能會比較模糊,比如BeanFactory和FactoryBean,詐一看,兩個沒啥區別,仔細研究後發現,其實本質上是兩個不同的單元。 概念 BeanFactory 字面意思講就是

    Spring中Bean的生命週期[email protected]方法進行物件的初始化

    方法:通過@Bean指定init-method和destroy-method; 注:單例項和原型模式物件的建立時間和初始化銷燬的時間順序不同。 一、單例項模式 1、建立Car例項物件,並建立初始化和銷燬方法 package com.atguigu.bean; imp

    Bean管理生命週期BeanPostProcessor

    package com.imooc.ioc.demo3; public interface UserDao { public void findAll(); public void

    Spark Streaming原始碼解讀Receiver在Driver的精妙實現全生命週期徹底研究思考

    在Spark Streaming中對於ReceiverInputDStream來說,都是現實一個Receiver,用來接收資料。而Receiver可以有很多個,並且執行在不同的worker節點上。這些Receiver都是由ReceiverTracker來管理的。

    Spring Bean的生命週期我的理解(五)------InitializingBean

    前言 Spring Bean建立後,提供了針對於Bean的兩種初始化方式: 實現InitializingBean介面; 設定init-method屬性; 本文介紹的是實現InitializingBean介面的方式; 實現 1.定義MyIniti

    Spark 定製版:010~Spark Streaming原始碼解讀流資料不斷接收全生命週期徹底研究思考

    本講內容: a. 資料接收架構設計模式 b. 資料接收原始碼徹底研究 注:本講內容基於Spark 1.6.1版本(在2016年5月來說是Spark最新版本)講解。 上節回顧 上一講中,我們給大傢俱體分析了Receiver啟動的方式及其啟動設計帶來的多個

    Spark定製班第9課:Spark Streaming原始碼解讀Receiver在Driver的精妙實現全生命週期徹底研究思考

    本期內容: 1. Receiver啟動的方式設想 2. Receiver啟動原始碼徹底分析 1. Receiver啟動的方式設想   Spark Streaming是個執行在Spark Core上的應用程式。這個應用程式既要接收資料,還要處理資料,這些都是在分散式的

    Spring Bean 生命週期“我從哪裡來?” 懂得這個很重要

    Spring bean 的生命週期很容易理解。例項化 bean 時,可能需要執行一些初始化以使其進入可用 (Ready for Use)狀態。類似地,當不再需要 bean 並將其從容器中移除時,可能需要進行一些清理,這就是它的生命週期 上一篇文章 面試還不知道BeanFactory和Applicati

    Spring Bean 生命週期destroy——終極信仰

    上一篇文章 Spring Bean 生命週期之我從哪裡來 說明了我是誰? 和 我從哪裡來? 的兩大哲學問題,今天我們要討論一下終極哲學我要到哪裡去? 初始化 Spring Bean 有三種方式: @PostConstruct InitializingBean.afterPropertiesSet() i

    從原始碼角度看Spring生命週期(官方最全)

    Spring在beanfactory中給出了spring的生命週期的list列表 一、bean初始化前的處理 Bean factory implementations should support the standard bean lifecycle interfaces as

    Spring Boot學習LogbackLog4j2整合與日誌發展史

    一、簡介 Java知名的日誌有很多,比如:JUL、Log4j、JCL、SLF4J、Logback、Log4j2,那麼這些日誌框架之間有著怎樣的關係?誕生的原因又是解決什麼問題?下面一起來看。 1.1 JUL Java有自己的日誌框架JUL(Java Util Logging)在java.

    iOS 生命週期的缺失錯亂

    不知道大家有沒有考慮過一個很奇怪的情況,就是 View Controller 的生命週期沒有被呼叫,或者是呼叫順序錯亂?其實這在實際操作中經常發生,override 的時候一不小心就忘記呼叫 super 了,或者明明是 override viewWillAppear(),卻呼叫成了 super.viewWil

    生命週期裝載

    裝載: 1. constructor 只會執行一次 構造這個函式進行一些初始化 2. static getDerivedStateFromProps() 在裝載階段和更新階段都會執行 rebder(){} 在裝載階段和更新階段也會執行

    Asp.Net Core中服務的生命週期選項區別用法

      在做一個小的Demo中,在一個介面上兩次呼叫檢視元件,並且在檢視元件中都呼叫了資料庫查詢,結果發現,一直報錯,將兩個檢視元件的呼叫分離,單獨進行,卻又是正常的,尋找一番,發現是配置依賴注入服務時,對於服務的生命週期沒有配置得當導致,特此做一次實驗來認識三者之間(甚至是四者之間的用法及區別)。 一、服務

    spring原始碼分析:spring生命週期

    接著上一篇我們看看具體是哪裡的程式碼執行了。 1.初始化BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory);--> PostProcessorRegistrationDelegate.

    spring原始碼分析:spring生命週期

    最近在看springboot自動配置,看到了@Conditional,@ConditionalOnMissingBean等等。這些註解,一直研究他們是如何實現springboot的條件註解的。由他們回到了@Configuration,回到了ConfigurationClassPostPr

    vue生命週期的理解一些面試題

    所有的生命週期鉤子自動繫結 this 上下文到例項中,因此你可以訪問資料,對屬性和方法進行運算。這意味著 你不能使用箭頭函式來定義一個生命週期方法 (例如 created: () => this.fetchTodos())。這是因為箭頭函式綁定了父上下文,因此 this 與你期待的 V

    Django請求生命週期響應內容

    Django請求生命週期: 1.傳送http請求2.伺服器接受,根據請求頭中的url在路由關係表中進行匹配(從上到下)3.匹配成功後,執行指定的views函式   URL -> 函式 ==>FBV   URL -> 類 ==>CBV4.業務處理   - 根據個人需求自定   - 操作