1. 程式人生 > >@AspectJ中關於`advice`註解的使用

@AspectJ中關於`advice`註解的使用

使用@AspectJ,需要額外匯入jar包,從官網下載即可,搜尋關鍵字`aspectj download`.

說明,在有些參考書中,advice譯為`增強`,依據其效用.

@Aspect 定義一個切面
@PointCut 定義複用指示器
@Before 前置通知
@After 後置通知

 @Around

環繞通知
@AfterReturning 返回通知
@AfterThrowing 異常通知

目標物件類

package siye;
import org.springframework.stereotype.Component;
@Component
public class TargetObj
{
	// 測試前置通知和後置通知
	public void work()
	{
		System.out.println("user_work");
	}
	// 測試異常通知.
	public void throwMethod()
	{
		throw new RuntimeException();
	}
	// 測試環繞通知.
	public void testAround()
	{
		System.out.println("test_around_advice");
	}
	// 測試返回通知,和引數擷取.
	public int testReturn(int num)
	{
		return num;
	}
}

測試@AspectJ註解的切面類

package siye;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component // 註冊元件.
@Aspect // 切面,即切點和通知的組合.
public class AspectJtoAnno
{
	@Pointcut("execution(* *.work(..))") // 定義可重用的指示器.
	public void myPointCut()
	{
	}
	/*
	 * 前置通知和後置通知.
	 */
	@Before("myPointCut()")
	public void testAnnoBefore()
	{
		System.out.println("方法即將執行----advice_before");
	}
	@After("myPointCut()")
	public void testAnnoAfter()
	{
		System.out.println("方法執行完畢-----advice_after");
	}
	/*
	 * 環繞通知.
	 */
	@Around("execution(* *.testAround(..))")
	public void testAnnoAround(ProceedingJoinPoint jp)
	{
		// ProceedingJoinPoint,唯一作用,通知中,呼叫被通知的方法.
		// 不呼叫,該通知阻塞被通知方法的呼叫.
		try
		{
			System.out.println("方法開始執行----advice_around");
			jp.proceed();
			System.out.println("方法執行完畢----advice_around");
		} catch (Throwable e)
		{
		}
	}
	/*
	 * 異常通知.
	 */
	@AfterThrowing("execution(* *.throwMethod(..))")
	public void testAnnoAfterThrowing()
	{
		System.out.println("方法丟擲異常----advice_throwing");
	}
	/*
	 * 返回通知和引數的獲取.
	 */
	/**
	 * 提取方法中的引數.
	 * name binding only allowed in target, this, and args pcds
	 * 
	 * execution和args組合使用
	 */
	@AfterReturning("execution(* *.testReturn(int)) && args(num)")
	public void testAnnoAfterReturning(int num)
	{
		System.out.println("提取出來的引數值是" + num);
		System.out.println("方法正確執行已返回-----after_returning");
	}
}

上下文配置類

package siye;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class ConfigClass
{
}

測試註解類

package siye;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
 * advice使用的5個註解.
 * org.aspectj.lang.annotation.After;
 * org.aspectj.lang.annotation.AfterReturning;
 * org.aspectj.lang.annotation.AfterThrowing;
 * org.aspectj.lang.annotation.Around;
 * org.aspectj.lang.annotation.Before;
 * 
 * 切面使用的註解.
 * org.aspectj.lang.annotation.Aspect;
 */
public class UnitTest
{
	public static void main(String[] args)
	{
		String packName = UnitTest.class.getPackage().getName();// 反射獲取包名稱.
		AnnotationConfigApplicationContext context =
				new AnnotationConfigApplicationContext();
		context.register(ConfigClass.class);
		context.scan(packName);// 取代@ComponentScan.
		context.refresh();
		// System.out.println(context);
		TargetObj targetObj = context.getBean(TargetObj.class);
		targetObj.work();
		targetObj.testAround();
		targetObj.testReturn(12);
		try
		{
			System.out.println();
			targetObj.throwMethod();
		} catch (Exception e)
		{
		}
		context.close();
	}
}