在瞭解SpringAOP之前先來了解下什麼是代理模式?
代理模式:是一個使用頻率非常高的設計模式,主要是爲其他對象提供一種代理以控制對這個對象的訪問。
動態代理的步驟:
1. 創建一個實現接口InvocationHandler的類,它必須實現invoke方法;
2.創建被代理的類及接口
3. 通過Proxy的靜態方法newProxyInstance(ClassLoaderHandler,Class[] interfaces, InvocationHandler h)創建一個代理
4. 通過代理調用接口方法
舉例說明(借鑑網上的例子):
老師讓同學A去丟垃圾,同學A不想去,於是叫了同學B幫忙丟,但是同學A又不放心同學B沒有把垃圾丟到垃圾桶,所以在一旁監督同學B,在合理的時間做合理的事情,老師就以爲是同學A丟的。
創建一個垃圾類:
public interface Rabbish{
//丟垃圾
void doRabbish();
}
操作丟垃圾,目標對象,根據例子來說,這個丟垃圾的操作是同學A也是同學B
public class HimB implements Rabbish{
@Override
public void doRabbish{
System.out.println(“Him doRabbish!!!”);
}
}
驅使目標對象去丟垃圾,即同學A讓同學B去丟垃圾
public class MineA implements Rabbish{
private HimB b;
@Override
public void doRabbish(){
//前置通知
System.out.println(“同學A請求同學B幫忙丟垃圾”);
//丟垃圾
try{
b.doRabbish();
}catch(Exception e){
//異常通知
system.out.println(e);
Throw e;
}
//後置通知
System.out.println(“垃圾已丟”);
}
}
接來下了解AOP:
Spring AOP是Spring框架的核心功能之一,面向切面編程,它利用了java代理機制模式實現,其思想就是通過預編譯方式和運行期間動態代理實現程序功能(例如登陸權限攔截,監控異常等)的統一維護。它可以將模塊劃分的更細緻,減少各模塊和公用模塊之間的耦合,讓我們將關注點轉移到業務本身。
下面來了解下AOP的幾個關鍵詞:
1. 切面(Aspect):切面是通知和切點的結合。通知和切點共同定義了切面的全部內容,切面可以使用通用類或者在普通類中定義@Aspect註解來實現。
2. 連接點(join point):指方法,一個連接點總是代表一個方法的執行。應用可能有數以千計的時機應用通知,這些時機稱之爲連接點。連接點是在應用執行過程中能夠插入切面的一個點,這個點可以是調用方法時,拋出異常時等。切面代碼可以利用這些點插入到應用到正常流程之中,並添加新的行爲。
3. 通知(Advice):切面的工作被稱之爲通知。
4. 切入點(Pointcut):切點的定義會匹配通知所要織入的一個或多個連接點,我們通常使用明確的類和方法名稱,或者利用正則表達式定義所匹配的類和方法名稱來指定這些切點。
5. 引入(Introduction):引入允許我們向現有類添加新方法或屬性。
6. 目標對象(Target Object):被一個或者多個切面所通知的對象。它通常是一個代理對象。也有人把它叫做被通知對象,既然Spring AOP是通過運行時代理實現的,這個對象永遠是一個被代理對象。
7. 織入(Weaving):織入是把切面應用到目標對象並創建新的代理對象的過程。
在SpringAOP中,關注點和橫切關注的區別?
關注點(concern)是應用中一個模塊的行爲,一個關注點可能會被定義爲一個我們想實現的一個功能。
橫切關注點(cross-cutting concern)是一個關注點,是整個應用都會使用的功能,並影響整個應用,例如日誌,安全和數據傳輸,幾乎應用的每個模塊都需要的功能。
切面通知的類型:
1. 前置通知(Before):在目標方法被調用之前調用通知功能;
2. 後置通知(after);在目標方法完成之後調用通知,此時不會關心方法的輸出是什麼;
3. 返回通知(after-returning):在目標方法成功執行之後調用通知;
4. 異常通知(after-throwing):在目標方法拋出異常後調用通知;
5. 環繞通知(Around):通知包裹了被通知的方法,在被通知的方法調用之前和調用之後執行自定義的行爲。
舉例說明AOP登陸攔截:
@Aspect
@Componment
public class LoginAspect{
//切入點
@Pointcut(value=“Execution(public * com.xxx.user ..*.*(..)))”)
public void pointCutMethod(){}
//環繞通知
@Around(value=“pointCutMethod()”)
public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
//業務邏輯處理
//返回方法的返回值
Object proceed = pjp.proceed();
}
}