1.Advice的主要類型:
- 前置通知 @Before:該註解標註的方法在業務模塊代碼執行之前執行,其不能阻止業務模塊的執行,除非拋出異常;
- 返回通知 @AfterReturning:該註解標註的方法在業務模塊代碼執行之後執行;
- 異常通知 @AfterThrowing:該註解標註的方法在業務模塊拋出指定異常後執行;
- 後置通知 @After:該註解標註的方法在所有的Advice執行完成後執行,無論業務模塊是否拋出異常,類似於finally的作用;
- 環繞通知 @Around:該註解功能最爲強大,其所標註的方法用於編寫包裹業務模塊執行的代碼,其可以傳入一個ProceedingJoinPoint用於調用業務模塊的代碼,無論是調用前邏輯還是調用後邏輯,都可以在該方法中編寫,甚至其可以根據一定的條件而阻斷業務模塊的調用;
- @DeclareParents:其是一種Introduction類型的模型,在屬性聲明上使用,主要用於爲指定的業務模塊添加新的接口和相應的實現。
- @Aspect:嚴格來說,其不屬於一種Advice,該註解主要用在類聲明上,指明當前類是一個組織了切面邏輯的類,並且該註解中可以指定當前類是何種實例化方式,主要有三種:singleton、perthis和pertarget,具體的使用方式後面會進行講解。
這裏需要說明的是,@Before是業務邏輯執行前執行,與其對應的是@AfterReturning,而不是@After,@After是所有的切面邏輯執行完之後纔會執行,無論是否拋出異常。
環繞通知順序:
2.切點表達式
博客地址:https://www.cnblogs.com/zhangxufeng/p/9160869.html
3.spring aop 利用JoinPoint獲取參數的值和方法名稱:
@Aspect
@Component
public class AspectCeShi {
@Pointcut("@within(com.ceshi.demo.demo.pingan.DynamicSwitchDataSource) || " +
"@annotation(com.ceshi.demo.demo.pingan.DynamicSwitchDataSource)")
public void pointcut(){}
@Before("pointcut()")
public void doBefore(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
Signature signature = joinPoint.getSignature();
Object target = joinPoint.getTarget();
Object aThis = joinPoint.getThis();
System.out.println(Arrays.toString(args));
System.out.println(signature);
System.out.println(target.toString());
System.out.println(aThis.toString());
}
}
AspectJ使用org.aspectj.lang.JoinPoint接口表示目標類連接點對象,如果是環繞增強時,使用org.aspectj.lang.ProceedingJoinPoint表示連接點對象,該類是JoinPoint的子接口。任何一個增強方法都可以通過將第一個入參聲明爲JoinPoint訪問到連接點上下文的信息。我們先來了解一下這兩個接口的主要方法:
1)JoinPoint
# 1.獲取連接點方法運行時的入參列表;
java.lang.Object[] getArgs()
# 注:獲取的是自定義註解方法的參數列表,以數組方式呈現,如果在運行下列方法時參數爲123,則獲取的數組# 裏面只有參數123
@DynamicSwitchDataSource
public void ceShiDao(String bb){
System.out.println("Dao方法執行了");
}
# 2.獲取連接點的方法簽名對象;
Signature getSignature()
# 注:獲取的是當前自定義註解(連接點)的方法簽名對象
# 方法對象爲:void com.ceshi.demo.demo.pingan.CeShiDao2.ceShiDao(String)
@DynamicSwitchDataSource
public void ceShiDao(String bb){
System.out.println("Dao方法執行了");
}
# 3.獲取連接點所在的目標對象;
java.lang.Object getTarget()
# 注:獲取的是當前自定義註解(連接點)方法所在的這個類
# 連接點所在的目標對象:CeShiDao2
public class CeShiDao2 {
@DynamicSwitchDataSource
public void ceShiDao(String bb){
System.out.println("Dao方法執行了");
}
}
# 4.獲取代理對象本身;
# 代理對象本身:CeShiDao2@173013d4
java.lang.Object getThis()
2)ProceedingJoinPoint
ProceedingJoinPoint繼承JoinPoint子接口,它新增了兩個用於執行連接點方法的方法:
# 通過反射執行目標對象的連接點處的方法;
java.lang.Object proceed() throws java.lang.Throwable
# 通過反射執行目標對象連接點處的方法,不過使用新的入參替換原來的入參。
java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable