Spring中Aop的實現
阿新 • • 發佈:2018-11-11
Spring中AOP的實現分為兩種:
一、Java配置實現
1、通過註解定義攔截規則
2、通過方法路徑定義攔截規則
二、XML配置實現
1、通過註解定義攔截規則
2、通過方法路徑定義攔截規則
一、Java配置實現
(1)Java配置實現,定義一個註解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAction {
}
(2)定義Target,Target中有部分方法加有註解,凡是加有註解的方法都會被攔截下來,沒加註解的方法則不受影響:
@Component
public class MyCalcultor {
@MyAction
public int add(int a, int b) {
System.out.println("add。。。");
return a + b; }
public String sayHello(String name) {
return "hello " + name + " !";
}
}
(3)定義切面,切面包含兩個部分:切點+增強(通知)分為五大類
*前置通知、通知在目標方法執行之前
*後置通知、通知在目標方法執行之後
*異常通知、通知在目標方法拋異常執行
*返回通知、通知在目標方法有返回值時執行
*環繞通知、包含了前面四種
@Component @Aspect public class LogAspect { /** * @param point 引數是指連線點,從這個引數中,可以獲取方法名方法引數等資訊 * @Before註解表示這是一個前置通知,該通知會在目標方法執行之前執行 */ @Before("@annotation(MyAction)") public void before(JoinPoint point) { String name = point.getSignature().getName(); System.out.println(name + "方法開始執行了..."); } }
(4)其他四種類型的通知
/**
* 這個類就是切面,該類中的內容包含兩大塊:切點+通知
*
* @Componet只是將該類註冊到Spring容器中
* @Aspect表示該類是一個切面
*/@Component
@Aspect
public class LogAspect {
/**
* @param point 引數是指連線點,從這個引數中,可以獲取方法名方法引數等資訊
* @Before註解表示這是一個前置通知,該通知會在目標方法執行之前執行
*/
@Before("@annotation(MyAction)")
public void before(JoinPoint point) {
String name = point.getSignature().getName();
System.out.println(name + "方法開始執行了...");
}
/**
* 這是一個後置通知,後置通知在目標方法執行結束後執行
* @param point
*/
@After("@annotation(MyAction)"){
System.out.println(point.getSignature().getName() + "方法執行結束了...");
}
/**
* 這是一個返回通知,可以獲取目標方法的返回值
*
* 方法中的引數名和註解中的引數名是對應的,引數值就是目標方法的返回值
*
* 需要注意返回值的型別,返回值的型別必須是引數的類或者子類
*/
@AfterReturning(value = "@annotation(MyAction)",returning = "result")
public void returning(JoinPoint point,Object result) {
System.out.println(point.getSignature().getName() + "方法的返回值是:" + result);
}
/**
* 這是一個異常通知,該通知在方法執行丟擲異常時執行
*
* 如果目標方法沒有異常,則通知不會被觸發
*/
@AfterThrowing(value = "@annotation(MyAction)",throwing = "e")
public void throwing(JoinPoint point,Exception e) { System.out.println(">>>>>"+e.getMessage());
}
/**
* 環繞通知是上面四種通知的集大成者,因為這個通知中包含了上面四種通知的功能
*
* @param pjp 這個引數類似於Method物件
* @return
*/
@Around("@annotation(MyAction)")
public Object around(ProceedingJoinPoint pjp) {
//pjp.proceed() 就類似於method.invoke()
try {
//寫在這個位置的,就是前置通知
Object proceed = pjp.proceed();
//寫在這個位置的,就是後置通知
return proceed;
}catch (Throwable throwable) {
//寫在這個位置的,就是異常通知
throwable.printStackTrace();
}
return null; }
}
(5)可以通過如下方法簡化切點的定義:
/**
* 可以單獨定義一個方法,專門用來定義切點,然後在其他方法中引用
*/
@Pointcut("@annotation(MyAction)")
public void pointcut() {
}
二、XML配置實現
(1)通過方法路徑定義攔截規則,實際上只是切點的定義方式變了,其他的還是一樣的。
/**
* 可以單獨定義一個方法,專門用來定義切點,然後在其他方法中引用
* 第一個* 表示目標方法的返回值,可以是任意型別,*表示任意型別
* 第二個*表示類中的任意方法
* 兩個.表示方法的引數任意(可有可無,型別任意)
*
* 例如,想精確定位到add方法,步驟如下:
* execution(int com.itbaizhan.service.MyCalcultor.add(int,int))
*/
@Pointcut("execution(* com.itbaizhan.service.*.*(..))")
public void pointcut() {
}
(2)使用表示式,可以較好的滿足最小侵入式原則。