1. 程式人生 > >Spring中的後置處理器BeanPostProcessor講解

Spring中的後置處理器BeanPostProcessor講解

BeanPostProcessor介面作用:

     如果我們想在Spring容器中完成bean例項化、配置以及其他初始化方法前後要新增一些自己邏輯處理。我們需要定義一個或多個BeanPostProcessor介面實現類,然後註冊到Spring IoC容器中。

package com.test.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
 * bean後置處理器
 * @author zss
 *
 */
public class PostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean,
            String beanName) throws BeansException {
        if ("narCodeService".equals(beanName)) {//過濾掉bean例項ID為narCodeService
            return bean;
        }
        System.out.println("後置處理器處理bean=【"+beanName+"】開始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean,
            String beanName) throws BeansException {
        if ("narCodeService".equals(beanName)) {
            return bean;
        }
        System.out.println("後置處理器處理bean=【"+beanName+"】完畢!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }

}

注意:介面中兩個方法不能返回null,如果返回null那麼在後續初始化方法將報空指標異常或者通過getBean()方法獲取不到bean例項物件 ,因為後置處理器從Spring IOC容器中取出bean例項物件沒有再次放回IOC容器中 。

將Spring的後置處理器PostProcessor配置到Spring配置檔案中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 定義一個bean -->
     <bean id="narCodeService" class="com.test.service.impl.NarCodeServiceImpl">
     </bean>
    <bean id="beanLifecycle" class="com.test.spring.BeanLifecycle" init-method="init" destroy-method="close">
        <property name="name" value="張三"></property>
        <property name="sex" value="男"></property>
    </bean>

    <!-- Spring後置處理器 -->
    <bean id="postProcessor" class="com.test.spring.PostProcessor"/>
</beans>

 BeanPostProcessor API:

public interface BeanPostProcessor {  
  
    /** 
     * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean 
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} 
     * or a custom init-method). The bean will already be populated with property values.    
     */  
    //例項化、依賴注入完畢,在呼叫顯示的初始化之前完成一些定製的初始化任務  
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;  
  
      
    /** 
     * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean 
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}   
     * or a custom init-method). The bean will already be populated with property values.       
     */  
    //例項化、依賴注入、初始化完畢時執行  
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;  
  
}
由API可以看出:
1:後置處理器的postProcessorBeforeInitailization方法是在bean例項化,依賴注入之後及自定義初始化方法(例如:配置檔案中bean標籤新增init-method屬性指定Java類中初始化方法、
@PostConstruct註解指定初始化方法,Java類實現InitailztingBean介面)之前呼叫
2:後置處理器的postProcessorAfterInitailization方法是在bean例項化、依賴注入及自定義初始化方法之後呼叫

注意:
   1.BeanFactory和ApplicationContext兩個容器對待bean的後置處理器稍微有些不同。ApplicationContext容器會自動檢測Spring配置檔案中那些bean所對應的Java類實現了BeanPostProcessor介面,並自動把它們註冊為後置處理器。在建立bean過程中呼叫它們,所以部署一個後置處理器跟普通的bean沒有什麼太大區別。

      2.BeanFactory容器註冊bean後置處理器時必須通過程式碼顯示的註冊,在IoC容器繼承體系中的ConfigurableBeanFactory介面中定義了註冊方法

/**  
     * Add a new BeanPostProcessor that will get applied to beans created  
     * by this factory. To be invoked during factory configuration.  
     * <p>Note: Post-processors submitted here will be applied in the order of  
     * registration; any ordering semantics expressed through implementing the  
     * {@link org.springframework.core.Ordered} interface will be ignored. Note  
     * that autodetected post-processors (e.g. as beans in an ApplicationContext)  
     * will always be applied after programmatically registered ones.  
     * @param beanPostProcessor the post-processor to register  
     */    
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

 Spring如何呼叫多個BeanPostProcessor實現類:

    我們可以在Spring配置檔案中新增多個BeanPostProcessor(後置處理器)介面實現類,在預設情況下Spring容器會根據後置處理器的定義順序來依次呼叫。

Spring配置檔案:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- bean定義 -->    
    <bean id="narCodeService" class="com.test.service.impl.NarCodeServiceImpl">
    </bean>
    <bean id="postProcessor" class="com.test.spring.PostProcessor"/>
    <bean id="postProcessorB" class="com.test.spring.PostProcessorB"/>
</beans>

BeanPostProcessor實現類:

package com.test.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
 * bean後置處理器
 * @author zss
 *
 */
public class PostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean,
            String beanName) throws BeansException {
        System.out.println("後置處理器處理bean=【"+beanName+"】開始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean,
            String beanName) throws BeansException {
        System.out.println("後置處理器處理bean=【"+beanName+"】完畢!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }
}
----------------------------------------------------------------------------------------------------------------------------------------
package com.test.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class PostProcessorB implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean,
            String beanName) throws BeansException {
        System.out.println("後置處理器開始呼叫了");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean,
            String beanName) throws BeansException {
        System.out.println("後置處理器呼叫結束了");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }
}

測試:

package com.test.spring;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class T {
    AbstractApplicationContext applicationcontext=null;
    @Before
    public void before() {
        System.out.println("》》》Spring ApplicationContext容器開始初始化了......");
        applicationcontext= new ClassPathXmlApplicationContext(new String[]{"test1-service.xml"});
        System.out.println("》》》Spring ApplicationContext容器初始化完畢了......");
    }
    @Test
    public void  test() {
        applicationcontext.registerShutdownHook();   
    }
}

測試結果:

》》》Spring ApplicationContext容器開始初始化了......
2017-03-19 10:50:29  INFO:ClassPathXmlApplicationContext-Refreshing org[email protected]18c92ff9: startup date [Sun Mar 19 10:50:29 CST 2017]; root of context hierarchy
2017-03-19 10:50:29  INFO:XmlBeanDefinitionReader-Loading XML bean definitions from class path resource [test1-service.xml]
後置處理器處理bean=【narCodeService】開始
後置處理器開始呼叫了
後置處理器處理bean=【narCodeService】完畢!
後置處理器呼叫結束了
》》》Spring ApplicationContext容器初始化完畢了......

2017-03-19 10:50:34  INFO:ClassPathXmlApplicationContext-Closing org[email protected]18c92ff9: startup date [Sun Mar 19 10:50:29 CST 2017]; root of context hierarchy

   在Spring機制中可以指定後置處理器呼叫順序,通過讓BeanPostProcessor介面實現類實現Ordered介面getOrder方法,該方法返回一整數,預設值為 0,優先順序最高,值越大優先順序越低

例如:

package com.test.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
/**
 * bean後置處理器
 * @author zss
 *
 */
public class PostProcessor implements BeanPostProcessor,Ordered{

    @Override
    public Object postProcessBeforeInitialization(Object bean,
            String beanName) throws BeansException {
        System.out.println("後置處理器處理bean=【"+beanName+"】開始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean,
            String beanName) throws BeansException {
        System.out.println("後置處理器處理bean=【"+beanName+"】完畢!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }

    @Override
    public int getOrder() {
        return 1;
    }
}
----------------------------------------------------------------------------
package com.test.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

public class PostProcessorB implements BeanPostProcessor,Ordered {

    @Override
    public Object postProcessBeforeInitialization(Object bean,
            String beanName) throws BeansException {
        System.out.println("後置處理器開始呼叫了");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean,
            String beanName) throws BeansException {
        System.out.println("後置處理器呼叫結束了");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

測試結果:

》》》Spring ApplicationContext容器開始初始化了......
2017-03-19 11:04:10  INFO:ClassPathXmlApplicationContext-Refreshing org[email protected]18c92ff9: startup date [Sun Mar 19 11:04:10 CST 2017]; root of context hierarchy
2017-03-19 11:04:10  INFO:XmlBeanDefinitionReader-Loading XML bean definitions from class path resource [test1-service.xml]
後置處理器開始呼叫了
後置處理器處理bean=【narCodeService】開始
後置處理器呼叫結束了
後置處理器處理bean=【narCodeService】完畢!

》》》Spring ApplicationContext容器初始化完畢了......
2017-03-19 11:04:14  INFO:ClassPathXmlApplicationContext-Closing org[email protected]18c92ff9: startup date [Sun Mar 19 11:04:10 CST 2017]; root of context hierarchy

相關推薦

Spring處理器BeanPostProcessor講解

BeanPostProcessor介面作用:      如果我們想在Spring容器中完成bean例項化、配置以及其他初始化方法前後要新增一些自己邏輯處理。我們需要定義一個或多個BeanPostProcessor介面實現類,然後註冊到Spring IoC容器中。 pack

Spring處理器BeanPostProcessor

一、Spring IOC容器中Bean的生命週期 Spring IOC容器可以管理Bean的生命週期,IOC容器允許在Bean生命週期的特定點執行定製的操作,即呼叫特定的方法。 1、Spring IOC容器對Bean的生命週期進行管理的過程: (1)、通過構造器

Spring原始碼分析:Spring處理器BeanPostProcessor

BeanPostProcessor簡介 BeanPostProcessor是Spring IOC容器給我們提供的一個擴充套件介面,如果我們需要在容器完成Bean的例項、初始化方法前後新增一些自己的邏輯處理,那麼定義一個BeanPostProcessor介面的實現類。

Spring容器擴充套件點:處理器BeanPostProcessor

先回顧bean生命週期的這張圖,看看BeanPostProcessor呼叫位置  通過上圖看到BeanPostProcessor(Bean後置處理器)兩個方法在bean生命週期的位置,即:在Spring容器完成Bean例項化和屬性設定後,並且在bean呼叫初始化方法之前或之

jmeter 處理器 JSR223 使用到的方法

1. log:用來記錄日誌檔案,寫入到jmeber.log檔案,使用方法:log.info(“This is log info!”); 2. ctx(JmeterContext)通過它來訪問context,使用方法可參考:org.apache.jmeter.threads.

曹工雜談:為什麼很少需要改Spring原始碼,因為擴充套件點太多了,說說Spring處理器

前言 最近發了好幾篇,都是覆蓋框架原始碼,但是spring的程式碼,我是從沒覆蓋過,畢竟,如果方便擴充套件,沒誰想去改原始碼,而spring就是不需要改原始碼的那個,真的是“對擴充套件開放,對修改關閉”的典範。 就我說曾經用過的,spring的擴充套件點,就包括了listener、beanFactoryPos

spring BeanPostProcessor處理器

這個介面有兩個方法: public interface BeanPostProcessor { @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName

關於Spring的Aware介面和處理器介面(BeanPostProcessor和BeanFactoryPostProcessor)的一些想法

看了關於Aware介面和後置處理器介面(BeanPostProcessor和BeanFactoryPostProcessor),感覺他們之間的功能有點亂,說一下他們之間的區別: (1)從呼叫時間點上看,Aware介面的方法(都是setXXX方法)是在Bean的屬性被設定之後

SpringBeanPostProcessor處理器與bean的生命週期

前言     本文將把Spring在Bean的生命週期中涉及到的後置處理器一一梳理出來,並簡要說一下功能,至於每個後置處理器在實際擴充套件中的用處,還要後續慢慢探索總結。 正文     下面一步步跟進探尋那些後置處理器們。首先進入AbstractApplicationC

Spring註解驅動開發】關於BeanPostProcessor處理器,你瞭解多少?

## 寫在前面 > 有些小夥伴問我,學習Spring是不是不用學習到這麼細節的程度啊?感覺這些細節的部分在實際工作中使用不到啊,我到底需不需要學習到這麼細節的程度呢?我的答案是:有必要學習到這麼細節的程度,而且是有機會、有條件一定要學!吃透Spring的原理和原始碼!往往拉開人與人之間差距的就是這些細

BeanPostProcessor bean 的處理器

exceptio col bject font for stp sys 方法 BE 一、MyBeanPostProcessor 類,自定 bean 的後只處理器類。當你在初始化容器中的 bean 之前和之後,都會調用該處理器中的方法 @Component //將該後後置處

Spring Aop底層原理詳解(利用spring處理器實現AOP)

寫在前面:對於一個java程式設計師來說,相信絕大多數都有這樣的面試經歷,面試官問:你知道什麼是aop嗎?談談你是怎麼理解aop的?等等諸如此類關於aop的問題。當然對於一些小白可能會一臉懵逼;對於一些工作一兩年的,可能知道,哦!aop就是面向切面變成,列印日誌啊,什麼什麼的,要是有點學

Spring Bean前置處理器的使用

Spirng中BeanPostProcessor和InstantiationAwareBeanPostProcessorAdapter兩個介面都可以實現對bean前置後置處理的效果,那這次先講解一下BeanPostProcessor處理器的使用 先看一下BeanPostPr

Spring學習 --------建立 Bean 處理器

                                                          建立 Bean 後置處理器 Bean 後置處理器允許在呼叫初始化方法前後對 Bean 進行額外的處理 Bean 後置處理器對 IOC 容器裡的所有 Bean

Spring註解驅動開發——bean的處理器

BeanPostProcessor:是一個介面,bean的後置處理器(實際是在bean的初始化前後執行操作) public class MyBeanPostProcessor implements BeanPostProcessor{ /** * bean是容器呼叫

Spring學習24】容器擴充套件點:處理器BeanFactoryPostProcessor

上篇說到的BeanPostProcessor(Bean後置處理器)常用在對bean內部的值進行修改;實現Bean的動態代理等。 BeanFactoryPostProcessor和BeanPostProcessor都是spring初始化bean時對外暴露的擴充套

spring-建立 Bean 處理器

Bean 後置處理器允許在呼叫初始化方法前後對 Bean 進行額外的處理. Bean 後置處理器對 IOC 容器裡的所有 Bean 例項逐一處理, 而非單一例項. 其典型應用是: 檢查 Bean 屬性

Spring Bean的生命週期、處理器、定義繼承

目錄: 瞭解Spring的基本概念 Spring簡單的示例 Spring Bean的定義及作用域 1.Bean的生命週期 Bean的生命週期可以簡單的理解為:Bean的定義——Bean的初始化——Bean的使用——Bean的銷燬 在其生命週期裡,有兩個重要的回撥方法,可以在初始化Bean和銷燬

Jmeter處理器

xtra 用戶信息 nbsp ssi 查詢 後置處理器 什麽是 cto tor 一、什麽是關聯? 將請求1的輸出 作為 請求2 的輸入,則稱之為關聯 二、通過JSON Path Extrator進行關聯 1、添加JSON Path Extractor(需要下載安裝插件)

第三篇 Postman之 Tests(處理器,斷言)

下一個 parse 後置處理器 token 9.png jmeter pri 獲取 strong 第二篇裏講了手動設置全局變量及局部變量的方法,但是這有一個缺點,就是每次測試之前,都需要獲取相關變量值,手動再填寫更新到對應的全局變量或者局部變量裏,這對於想進行自動化執行的人