天天看點

Spring-AOP 增強(Advice)5種類型和建立增強類概述增強類型提示

文章目錄

  • 概述
  • 增強類型
    • 前置增強
      • 執行個體一:通過代碼實作增強
      • 執行個體二 通過配置檔案實作前置增強-ProxyFactory
    • 後置增強
    • 環繞增強
    • 異常抛出增強
    • 引介增強
  • 提示

概述

Spring使用增強類定義橫切邏輯,同時由于Spring隻支援方法連接配接點,增強還包括在方法的哪一點加入橫切代碼的方位資訊,是以增強既包括橫切邏輯,又包括部分連接配接點的資訊

增強類型

AOP聯盟為增強定義了org.aopalliance.aop.Advice接口。

先了解一下增強接口的繼承關系

Spring-AOP 增強(Advice)5種類型和建立增強類概述增強類型提示
  • 帶Spring标志的是Spring定義的擴充增強接口
  • 帶aopalliance标志的是AOP聯盟所定義的接口

按照增強在目标類方法連接配接點的位置可以将增強劃分為以下五類:

  1. 前置增強 (org.springframework.aop.BeforeAdvice) 表示在目标方法執行前來實施增強
  2. 後置增強 (org.springframework.aop.AfterReturningAdvice)

    表示在目标方法執行後來實施增強

  3. 環繞增強 (org.aopalliance.intercept.MethodInterceptor)

    表示在目标方法執行前後同時實施增強

  4. 異常抛出增強 (org.springframework.aop.ThrowsAdvice) 表示在目标方法抛出異常後來實施增強
  5. 引介增強 (org.springframework.aop.introductioninterceptor)

    表示在目标類中添加一些新的方法和屬性

其中引介增強是一種特殊的增強。它可以在目标類中添加屬性和方法,通過攔截定義一個接口,讓目标代理實作這個接口。

  • 引介增強的連接配接點是類級别的,而前面的幾種則是方法級别的。
  • 環繞增強是AOP聯盟定義的接口,其他四種增強接口則是Spring定義的接口。

這些增強接口都有一些方法,通過實作這些接口方法,并在接口方法中定義橫切邏輯,就可以将它們織入目标類方法的相應連接配接點位置。

用Spring實作的話: 通過實作這些增強接口,在實作這些接口的方法當中定義橫切邏輯,然後通過配置Spring的配置檔案就可以完成将增強織入到目标方法當中了。

前置增強

在Spring當中,僅支援方法級别的增強,利用MethodBeforeAdvice實作,表示在目标方法執行前實施增強

執行個體一:通過代碼實作增強

代碼已托管到Github—> https://github.com/yangshangwei/SpringMaster

示例示範: 對服務生的服務用語進行強制規範。

我們假設服務生隻需要幹兩件事情:

  • 1.歡迎顧客
  • 2.對顧客提供服務
Spring-AOP 增強(Advice)5種類型和建立增強類概述增強類型提示

代碼說明:

建立業務接口類:Waiter.java

建立業務實作類:NativeWaiter.java

建立業務增強類:GreetingBeforeAdvice.java

建立增強測試類:BeforceAdviceTest.java

業務接口類

package com.xgj.aop.spring.advice.beforceAdvice;

public interface Waiter {

	void greetTo(String name);

	void serverTo(String name);
}           

複制

業務實作類

package com.xgj.aop.spring.advice.beforceAdvice;

public class NaiveWaiter implements Waiter {

	@Override
	public void greetTo(String name) {
		System.out.println("greetTo " + name + "\n");
	}

	@Override
	public void serverTo(String name) {
		System.out.println("serverTo " + name);
	}

}           

複制

業務增強類

package com.xgj.aop.spring.advice.beforceAdvice;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class GreetingBeforeAdvice implements MethodBeforeAdvice {

	/**
	 * 前置增強方法 當該方法發生異常時,将阻止目标方法的執行
	 * 
	 * @param method
	 *            目标類方法
	 * @param objects
	 *            目标類方法入參
	 * @param target
	 *            目标類對象執行個體
	 * @throws Throwable
	 */
	@Override
	public void before(Method method, Object[] args, Object target)
			throws Throwable {
		String clientName = (String) args[0];
		System.out.println("How are you " + clientName + " ?");
	}
}           

複制

說明:

BeforeAdvice是前置增強的接口,方法前置增強的MethodBeforeAdvice接口是其子類。 Spring目前僅提供方法調用的前置增強。

MethodBeforeAdvice接口定義了唯一的方法

void before(Method method, Object[] args, Object target) throws Throwable;           

複制

Spring-AOP 增強(Advice)5種類型和建立增強類概述增強類型提示

參數解釋:

  • method:目标類的方法
  • args:目标類方法的入參
  • target:目标類執行個體

當該方法發生異常時,将阻止目标類方法的執行

業務測試類

package com.xgj.aop.spring.advice.beforceAdvice;

import org.junit.Test;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

public class BeforceAdviceTest {
	@Test
	public void test() {
		// 建立目标對象
		Waiter target = new NaiveWaiter();
		// 建立增強類對象
		BeforeAdvice advice = new GreetingBeforeAdvice();

		// (1)建立代理工廠對象 - Spring提供的代理工廠
		ProxyFactory factory = new ProxyFactory();

		// (2)設定代理目标
		factory.setTarget(target);

		// (3)為代理目标添加增強
		factory.addAdvice(advice);

		// (4)擷取代理類
		Waiter proxy = (Waiter) factory.getProxy();

		// 調用目标類方法
		proxy.greetTo("Xiao");
		proxy.serverTo("GongJiang");
	}
}           

複制

運作單元測試:

Spring-AOP 增強(Advice)5種類型和建立增強類概述增強類型提示

執行個體二 通過配置檔案實作前置增強-ProxyFactory

我們上面的前置增強是使用org.springframework.aop.framework.ProxyFactory通過編碼的方式将GreetingBeforeAdvice的增強織入目标類NaiveWaiter中,那如何通過Spring配置檔案的方式實作同樣的效果呢?

請參考另外一篇博文 Spring-AOP 通過配置檔案實作前置增強-ProxyFactory

後置增強

請參閱另外一篇部落格 Spring-AOP 通過配置檔案實作 後置增強

環繞增強

請參閱另外一篇部落格 Spring-AOP 通過配置檔案實作 環繞增強

異常抛出增強

請參閱另外一篇部落格 Spring-AOP 通過配置檔案實作 異常抛出增強

引介增強

請參閱另外一篇部落格 Spring-AOP 通過配置檔案實作 引介增強

提示

在Spring4.0中,基于CGLib的類代理不再要求目标類必須有無參構造函數。這樣在使用CGLib類時,不再需要特别關注目标類是否有無參構造函數。 這樣的話,增強的目标Bean就可以使用構造函數注入了。