1. 程式人生 > >spring學習筆記(8)AOP增強(advice)配置與應用

spring學習筆記(8)AOP增強(advice)配置與應用

增強型別

增強(advice)主要包括如下五種型別
1. 前置增強(BeforeAdvice):在目標方法執行前實施增強
2. 後置增強(AfterReturningAdvice):在目標方法執行後實施增強
3. 環繞增強(MrthodInterceptor):在目標方法執行前後實施增強
4. 異常丟擲增強(ThrowsAdvice):在目標方法丟擲異常後實施增強
5. 引介增強(IntroductionIntercrptor):在目標類中新增一些新的方法和屬性

前置增強和後置增強配置

下面通過例項程式碼來分析前置增強,假如現在要作日誌記錄,記錄了什麼人呼叫什麼方法。前置增強的配置可歸納為如下步驟:

1. 配置代理介面:

package test.aop;

public interface ITarget {
    String speak(String name);
}

2. 定義被代理物件

package test.aop;
//被代理物件
public class Target implements ITarget{

    private static final String name = "zenghao";
    @Override
    public String speak(Integer age){
        System.out.println("hello I'm "
+ age + " years old"); return "I'm return value"; } public static String getName() { return name; } }

3. 配置增強

package test.aop;

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

public class BeforeAdvice implements MethodBeforeAdvice
{
/** * @param method:目標類的方法 * args: 目標類的方法入參 * obj:目標類例項 * */ @Override public void before(Method method, Object[] args, Object target) throws Throwable { if(target instanceof Target){ System.out.println("前置日誌記錄: " + ((Target)target).getName() + "呼叫了" + method.getName() + "方法,傳入引數為:" + args[0] ); } } } /*------------------分割線---------------------*/ package test.aop; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; import org.springframework.aop.MethodBeforeAdvice; public class AfterAdvice implements AfterReturningAdvice { /** * @param * returnValue 返回值 * method:目標類的方法 * args: 目標類的方法入參 * obj:目標類例項 * */ @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { if(target instanceof Target){ System.out.println("後置日誌記錄: " + ((Target)target).getName() + "呼叫了" + method.getName() + "方法,返回值為:" + returnValue ); } } }

4. 配置代理物件ProxyFactoryBean

PeoxyFactoryBean是FactoryBean的實現類,我們知道FactoryBean負責初始化Bean,而ProxyFactoryBean則負責為其他Bean建立代理例項,通過在xml中配置後注入使用

<!--  配置被代理物件 -->
<bean id="mytarget" class="test.aop.Target" />
<!-- 配置前置增強  -->
<bean id="myBeforeAdvice" class="test.aop.BeforeAdvice" />
<!-- 配置後置增強 -->
<bean id="myAfterReturnAdvice" class="test.aop.AfterAdvice" />
<!-- 配置代理物件 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean" >
    <!-- 配置代理介面集 -->
    <property name="proxyInterfaces" value="test.aop.ITarget" />
    <!-- 代理目標物件需要實現的介面,可以通過<list>標籤設定多個 -->
    <!-- 把通知織入代理物件 -->
    <property name="interceptorNames" >
        <list>
                <idref bean="myBeforeAdvice"/>
                <idref bean="myAfterReturnAdvice"/>
            </list>
    </property><!-- 配置實現了Advice增強介面的Bean,以bean名字進行指定 -->
    <property name="targetName" value="mytarget"></property><!-- 代理的目標物件 -->
</bean>

5. 測試

package test.aop;

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

public class TestAOP {

    private ApplicationContext ac;
    @Before
    public void setup(){
        ac = new ClassPathXmlApplicationContext("classpath:test/aop/aop.xml");
    }

    @Test
    public void test(){
        ITarget iTarget = (ITarget) ac.getBean("proxyFactoryBean");
        iTarget.speak(21);
    }
}

測試列印:

前置日誌記錄: zenghao呼叫了speak方法,傳入引數為:21
hello I’m 21 years old
後置日誌記錄: zenghao呼叫了speak方法,返回值為:I’m return value

環繞增強配置

在前面的基礎上,我們新增環繞增強類:

package test.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AroundAdvice implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println(invocation.getArguments()[0] + "——" +
        invocation.getStaticPart() + "——" +
        invocation.getThis().getClass() + "——" +
        invocation.getMethod().getName());
        invocation.proceed();//反射呼叫目標物件方法
        System.out.println("環繞增強呼叫結束");
        return "I'm around return value";
    }
}

在aop.xml中類似前置增強增加環繞增強配置,執行測試方法,得到結果:

前置日誌記錄: zenghao呼叫了speak方法,傳入引數為:21
21——public abstract java.lang.String test.aop.ITarget.speak(java.lang.Integer)——class test.aop.Target——speak
hello I’m 21 years old
環繞增強呼叫結束
後置日誌記錄: zenghao呼叫了speak方法,返回值為:I’m around return value
從以上我們能看到,當同時使用環繞增強和前後置增強時,它們的執行順序

異常增強配置

常用場景為配置實物管理器,當進行資料庫操作的方法發生異常時,可被異常增強捕獲,進行失誤回滾等操作。一個丟擲異常增強的例項如下所示:

package test.aop;

import java.lang.reflect.Method;
import java.sql.SQLException;

import org.springframework.aop.ThrowsAdvice;

public class ExceptionAdvice implements ThrowsAdvice {
    public void AfterThrowing(SQLException e){
        System.out.println(e.getMessage());
    }
    public void AfterThrowing(RuntimeException e){
        System.out.println(e.getMessage());
    }
    public void AfterThrowing(Method method, Object[] args, Object target,SQLException e){
        System.out.println(e.getMessage());
    }
}

其中有幾點是需要注意的:
1. 方法名必須為:afterThrowing
2. 三個入參Method method, Object[] args, Object target 要麼一起提供,要麼都不提供,而最後一個入參必須為Throwable或其子類。當目標物件丟擲異常時,增強會呼叫相似度最高的匹配異常類的方法(在類的繼承樹上,兩個類的距離越近,相似度就越高)

關於引介增強,它可以動態地為類增加新的介面或方法,具有難以想象的動態特性,在後面的學習中我們會再單獨提到。

相關推薦

spring學習筆記(8)AOP增強advice配置應用

增強型別 增強(advice)主要包括如下五種型別 1. 前置增強(BeforeAdvice):在目標方法執行前實施增強 2. 後置增強(AfterReturningAdvice):在目標方法執行後實施增強 3. 環繞增強(MrthodIntercept

AOP中的連線點Joinpoint、切點Pointcut增強Advice、引介Introduction、織入Weaving、切面Aspect

連線點(Joinpoint):程式執行的某個特定位置(如:某個方法呼叫前、呼叫後,方法丟擲異常後)。一個類或一段程式程式碼擁有一些具有邊界性質的特定點,這些程式碼中的特定點就是連線點。Spring僅支援方法的連線點。 切點(Pointcut):如果連線點相當於資料中的記錄,那麼

你如何理解AOP中的連線點Joinpoint、切點Pointcut增強Advice、引介Introduction、織入Weaving、切面Aspect這些概念?

a. 連線點(Joinpoint):程式執行的某個特定位置(如:某個方法呼叫前、呼叫後,方法丟擲異常後)。一個類或一段程式程式碼擁有一些具有邊界性質的特定點,這些程式碼中的特定點就是連線點。Spring僅支援方法的連線點。  b. 切點(Pointcut):如果連線點相當

Spring學習筆記02(AOP)

學了IOC之後,緊跟著就是AOP(面向切面程式設計) 來個官方一點的,面向切面程式設計,是通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。 簡單舉個例子來說,我們通過java程式碼對資料庫進行增刪改操作的時候,需要對事務進行控制,我們阻止事務的自動提交,事務成功後手動提交

spring-cloud學習筆記Eureka註冊中心修改成IP顯示

修改配置類 eureka: instance: #使用IP訪問註冊中心 prefer-ip-address: true #在註冊中心status的時候顯示的格式,這裡是 ip:埠 instance-id: ${spring.cloud.c

Spring學習筆記 使用Static Factory靜態工廠類建立Bean

普通定義Bean並且進行初始化的方法一般通過property(屬性)的setter方法或者構造方法進行。例如 <bean id="beanName" class="com.csdn.net.arvin.BeanClass" > <construct

spring學習筆記(7)AOP前夕[2]CGLib動態代理例項解析

CGLib動態代理基本原理 CGLib——Code Generation Library,它是一個動態位元組程式碼生成庫,基於asm。使用CGLib時需要匯入asm相關的jar包。而asm又是何方神聖? asm是一個java位元組碼操縱框架,它能被用來

學習筆記aop基於IOC容器的配置MSTzhang

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

Spring Cloud學習筆記1——服務治理Eureka

1、搭建服務註冊中心 1)新建一個Spring Boot專案,取名為EurekaServer,程式碼見碼雲:https://gitee.com/wudiyong/EurekaServer.git,然後在pom.xml檔案中加入依賴: <parent> &

【安全牛學習筆記】Web掃描器1

安全 web 漏洞 1.偵察httrack可將目標網站的網頁全部爬取下來,減少偵察過程中與目標服務器發生的交互。 2.Nikto(1).檢測對象 掃描軟件版本 搜索存在安全隱患的文件 配置漏洞

JavaSE 學習筆記之接 口

之前 rac 關鍵字 extends 修飾符 對象 clas con 而且 接 口: 1:是用關鍵字interface定義的。 2:接口中包含的成員,最常見的有全局常量、抽象方法。 註意:接口中的成員都有固定的修飾符。 成員變量:public static fina

JavaSE 學習筆記之多態

會有 轉換 容易 per 不同 如何 person 特點 一句話 多 態:函數本身就具備多態性,某一種事物有不同的具體的體現。 體現:父類引用或者接口的引用指向了自己的子類對象。//Animal a = new Cat(); 多態的好處:提高了程序的擴展性。 多態的弊端

JavaSE 學習筆記之Java概述

environ 電子 6.0 run javase 有一點 架構 spa form 一、Java的三種技術架構: JAVAEE:Java Platform Enterprise Edition,開發企業環境下的應用程序,主要針對web程序開發; JAVASE:Java P

python學習筆記文件操作

python1、文件操作流程:打開文件,得到文件句柄並賦值給一個變量通過句柄對文件進行操作關閉文件如下文件:2017-03-24 11:25:06:349 - info: [debug] [AndroidBootstrap] Sending command to android: {"cmd":"shutdo

設計模式學習筆記 C#代碼

內容 編程 繼承 color 模式 c# 派生類 ive spa 《深入淺出設計模式》學習筆記第一章 原始需求和設計 事情是這樣開始的,公司需要做一套程序,鴨子,設計如下: 一個鴨子父類,多個派生類,三個可override的方法。 第一次需求變更 我們要會飛的鴨子!!!!

FPGA軟硬協同設計學習筆記及基礎知識

擴展性 產生 新的 pll 多個 分配 每次 調用 span 一、FPGA軟件硬件協同定義: 軟件:一般以軟件語言來描述,類似ARM處理器的嵌入式設計。硬件定義如FPGA,裏面資源有限但可重配置性有許多優點,新的有動態可充配置技術。

多線程編程學習筆記——線程同步

als 執行 homepage auto using 發的 進行 read 函數 接上文 多線程編程學習筆記-基礎(一) 接上文 多線程編程學習筆記-基礎(二) 接上文 多線程編程學習筆記-基礎(三) 就如上一篇文章(多線程編程學習筆記-基礎(三))

多線程編程學習筆記——線程同步

class gen hybird 進行 syn locks finall nal nbsp 接上文 多線程編程學習筆記——線程同步(一) 接上文 多線程編程學習筆記——線程同步(二) 七、使用Barrier類

matlab學習筆記之常用命令

plot 我們 all 查看 學習 ear tla clear 但是 一.清除命令。   1.clear all;%清除所有變量,通常在matlab的工作區;另外斷點也會被清除掉   2.close all;%關閉所有窗口(除了編輯器窗口、命令窗口、幫助窗口)   3.cl

Redis學習筆記--Redis客戶端

本機 -c trace 圖形 tro cli family 毫秒 ati 1.Redis客戶端 1.1 Redis自帶的客戶端   (1)啟動   啟動客戶端命令:[root@kwredis bin]# ./redis-cli -h 127.0.0.1 -p 6379