SPring-AOP

2019-06-12
面向切面編程(AOP):應(yīng)用程序在運行時,由Spring動態(tài)地將切面織入到應(yīng)用程序指定的業(yè)務(wù)方法中。

切面(Aspect):是把在眾多業(yè)務(wù)中普遍存在的共有代碼抽取出來封裝為切面類集中管理,在程序運行時,由Spring容器運用動態(tài)代理技術(shù)在指定業(yè)務(wù)中自動織入這些切面。

什么是動態(tài)代理

AOP技術(shù)建立在動態(tài)代理機制之上。系統(tǒng)運行時,Spring會動態(tài)創(chuàng)建一個代理對象(Proxy)供使用者調(diào)用,該代理對象已經(jīng)將切面織入到目標對象的業(yè)務(wù)方法中,從而使切面的功能與目標對象的業(yè)務(wù)功能同時得以執(zhí)行。

調(diào)用者直接調(diào)用的其實是Spring動態(tài)生成的代理對象,再由代理對象調(diào)用目標對象完成原始的業(yè)務(wù)處理,而代理對象則已經(jīng)將切面與業(yè)務(wù)邏輯方法進行了合成。

使用注解方式實現(xiàn)AOP

設(shè)計切面類,編寫切面通知

@Component
@Aspect
public class LogAspect {
     //注解里使用的變量只能是final String類型
     public static final String EDP = "execution(* com.controller.LoginController.*(..))";

     @Before(EDP) //前置通知
     public void beforeAdvice(JoinPoint joinpoint) {}

     @AfterReturning(EDP) //后置通知
     public void afterReturningAdvice(JoinPoint joinpoint) {}

     @AfterThrowing(pointcut = EDP, throwing = "e") //異常通知
     public void afterThrowingAdvice(JoinPoint joinpoint, Exception e) {}

     @After(EDP) //最終通知
     public void afterAdvice(JoinPoint joinpoint) {}

     @Around(EDP) //環(huán)繞通知
     public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
         Object result = pjp.proceed();// 傳遞給連接點對象進行接力處理
         return result;
     }
}

1.什么是通知

通知(Advice)是切面的具體功能,通常是切面類中的方法。以目標方法連接點為參照,根據(jù)這個通知欲切入到目標方法的位置不同可分為:

  • 前置通知(Before):是指在某個連接點方法之前執(zhí)行的通知。如果這個通知不拋出異常,那么該連接點就一定會被執(zhí)行。常用于權(quán)限管理。
  • 后置通知(AfterReturning):是指某個連接點方法正常完成(沒有拋出異常)后執(zhí)行的通知。常用于IO流關(guān)閉、臨時文件刪除等。
  • 異常通知(AfterThrowing):是指在連接點方法拋出異常退出時執(zhí)行的通知。常用于異常處理、日志記錄等。
  • 最終通知(After):是指無論在任何情況下連接點方法退出時執(zhí)行的通知,也就是說無論連接點方法正常退出還是拋出異常退出都會執(zhí)行此通知。類似于異常處理機制中finally塊的作用,常用于釋放資源。
  • 環(huán)繞通知(Around):是指包圍連接點方法的通知。這種通知功能非常強大,可以替代前面任意一種通知的功能。常用于日志記錄、事務(wù)處理。

2.AOP注解說明

  • @Aspect:使用@Aspect注解的類,Spring會當作切面類處理。
  • @Before:前置通知
  • @AfterReturning:后置通知
  • @AfterThrowing:異常通知
  • 必須使用@AfterThrowing(pointcut = 連接點,throwing = "e")的形式,否則會出現(xiàn)”error at ::0 formal unbound in pointcutd”錯誤
  • @After:最終通知
  • @Around:環(huán)繞通知
  • @Pointcut:定義切入點表達式,需要同時定義一個切入點方法,返回值為void且方法體為空

3.切入點表達式

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? 
    name-pattern(param-pattern) throws-pattern?) 

說明:

  • 訪問類型模式(modifiers-pattern):方法的訪問類型,如public表示匹配所有公用方法,此模式通常可省略不寫,除非有特定需求。
  • 返回值類型模式(ret-type-pattern):方法的返回值類型,設(shè)置為*表示匹配任意的返回值類型。
  • 類型名稱模式(declaring-type-pattern):表示匹配的包或類的名稱規(guī)則,"包路徑.*"表示指定包下的所有類均予以匹配,"包路徑..*"則表示指定包及其子包下的所有類均予以匹配,"包路徑.類名"表示指定的類予以匹配。
  • 名字模式(name-pattern):匹配方法名,*表示匹配所有方法,set*表示所有方法名以set開頭的方法。
    參數(shù)模式(param-pattern): ()表示匹配不接受任何參數(shù)的方法,(..)表示匹配接受任意數(shù)量參數(shù)的方法,(*)表示匹配接受一個任何類型的參數(shù)的方法, (*,String)則表示匹配接受兩個參數(shù)的方法,第一個參數(shù)可以是任意類型,而第二個參數(shù)必須是String類型。
  • 異常模式(throws-pattern):拋出何種類型的異常,如RuntimeException表示匹配拋出RuntimeException異常的方法,此模式通??墒÷圆粚懀怯刑囟ǖ男枨?。
切入點正則表達式 功 能 描 述
execution(public * *(..)) 匹配所有公有方法
execution(* set*(..)) 匹配所有以“set”開頭的方法
execution(* com.action.UserController.*(..)) 匹配UserController類的所有方法
execution(* com.action..(..)) 匹配com.action包下所有類的所有方法
execution(* com.action...(..)) 匹配com.action包及子包下所有類的所有方法

修改Spring配置文件

啟動基于注解的AspectJ支持

<aop:aspectj-autoproxy />
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容