日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AspectJ详解

發(fā)布時(shí)間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AspectJ详解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

      • Spring AOP
        • AspectJ
          • 引入aspectj的相關(guān)jar包
          • 在spring中啟用aspectj
          • 編寫注解
          • 自定義實(shí)現(xiàn)Aspect
            • Pointcut
            • #execution表示式(方法描述匹配)
            • 方法參數(shù)匹配
            • 當(dāng)前AOP代理對象類型匹配
            • 目標(biāo)類匹配
            • 標(biāo)有此注解的方法匹配
          • 在目標(biāo)方法上添加注解

Spring AOP

AOP使用場景:權(quán)限控制、異常處理、緩存、事務(wù)管理、日志記錄、數(shù)據(jù)校驗(yàn)等等

AOP基本概念

  • 切面(Aspect): 程序運(yùn)行過程中的某個(gè)的步驟或者階段
  • 連接點(diǎn)(Joinpoint): 程序運(yùn)行過程中可執(zhí)行特定處理(增強(qiáng)處理)的點(diǎn), 如異常處理。而在SpringAOP中,方法調(diào)用是連接點(diǎn)。
  • Advice(通知、處理、增強(qiáng)處理): 在符合的連接點(diǎn)進(jìn)行的特定處理 (增強(qiáng)處理)
  • 切入點(diǎn)(Pointcut): 可切入進(jìn)行增強(qiáng)處理的連接點(diǎn)。AOP核心之一就是如何用表達(dá)式來定義符合的切入點(diǎn)。在Spring中,默認(rèn)使用AspectJ的切入點(diǎn)語法。

由于Spring AOP只支持以Spring Bean的方法調(diào)用來作為連接點(diǎn), 所以在這里切入點(diǎn)的定義包括:

  • 切入點(diǎn)表達(dá)式, 來限制該能作用的范圍大小,即是,能匹配哪些bean的方法
  • 命名切入點(diǎn)

AspectJ

參考:Spring AOP @Before @Around @After 等 advice 的執(zhí)行順序

執(zhí)行順序
無異常情況:Around->Before->自己的method->Around->After->AfterReturning
異常情況:Around->Before->自己的method->Around->After->AfterThrowing

多個(gè)Aspect作用于一個(gè)方法上,如何指定每個(gè) aspect 的執(zhí)行順序呢?
方法有兩種:

  • 實(shí)現(xiàn)org.springframework.core.Ordered接口,實(shí)現(xiàn)它的getOrder()方法
  • 給aspect添加@Order注解,該注解全稱為:org.springframework.core.annotation.Order
@Order(5) @Component @Aspect public class Aspect1 {}@Order(6) @Component @Aspect public class Aspect2 {}

注意點(diǎn)

  • 如果在同一個(gè) aspect 類中,針對同一個(gè) pointcut,定義了兩個(gè)相同的 advice(比如,定義了兩個(gè) @Before),那么這兩個(gè) advice 的執(zhí)行順序是無法確定的,哪怕你給這兩個(gè) advice 添加了 @Order 這個(gè)注解,也不行。這點(diǎn)切記。
  • 對于@Around這個(gè)advice,不管它有沒有返回值,但是必須要方法內(nèi)部,調(diào)用一下 pjp.proceed();否則,Controller 中的接口將沒有機(jī)會(huì)被執(zhí)行,從而也導(dǎo)致了 @Before這個(gè)advice不會(huì)被觸發(fā)。

使用步驟

引入aspectj的相關(guān)jar包
<!--使用AspectJ方式注解需要相應(yīng)的包--> <dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>${aspectj.version}</version> </dependency> <!--使用AspectJ方式注解需要相應(yīng)的包--> <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>${aspectj.version}</version> </dependency>
在spring中啟用aspectj
<aop:aspectj-autoproxy proxy-target-class="true" />
編寫注解
import java.lang.annotation.*;/*** api攔截器,記錄日志*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented//文檔生成時(shí),該注解將被包含在javadoc中,可去掉 public @interface ApiInf { }
自定義實(shí)現(xiàn)Aspect

注意注解@Aspect,如果沒有使用@Component,則需要在spring中注冊該aspect的bean

<bean class="com.ufgov.util.rest.ApiLogAspect" />

參考:Spring AOP 中@Pointcut的用法

Pointcut

@Pointcut:Pointcut的定義包括兩部分:Pointcut表達(dá)式(expression:就是@Pointcut后邊的參數(shù))和Pointcut簽名(就是@Pontcut所在的方法名稱),Pointcut簽名在下邊@Before和@After等中使用(相當(dāng)于使用Pointcut表達(dá)式)。

#execution表示式(方法描述匹配)

表達(dá)式類型

標(biāo)準(zhǔn)的Aspectj Aop的pointcut的表達(dá)式類型是很豐富的,但是Spring Aop只支持其中的9種,外加Spring Aop自己擴(kuò)充的一種一共是10種類型的表達(dá)式,分別如下。

  • execution:一般用于指定方法的執(zhí)行,用的最多。
  • within:指定某些類型的全部方法執(zhí)行,也可用來指定一個(gè)包。
  • this:Spring Aop是基于代理的,生成的bean也是一個(gè)代理對象,this就是這個(gè)代理對象,當(dāng)這個(gè)對象可以轉(zhuǎn)換為指定的類型時(shí),對應(yīng)的切入點(diǎn)就是它了,Spring Aop將生效。
  • target:當(dāng)被代理的對象可以轉(zhuǎn)換為指定的類型時(shí),對應(yīng)的切入點(diǎn)就是它了,Spring Aop將生效。
  • args:當(dāng)執(zhí)行的方法的參數(shù)是指定類型時(shí)生效。
  • @target:當(dāng)代理的目標(biāo)對象上擁有指定的注解時(shí)生效。
  • @args:當(dāng)執(zhí)行的方法參數(shù)類型上擁有指定的注解時(shí)生效。
  • @within:與@target類似,看官方文檔和網(wǎng)上的說法都是@within只需要目標(biāo)對象的類或者父類上有指定的注解,則@within會(huì)生效,而@target則是必須是目標(biāo)對象的類上有指定的注解。而根據(jù)筆者的測試這兩者都是只要目標(biāo)類或父類上有指定的注解即可。
  • @annotation:當(dāng)執(zhí)行的方法上擁有指定的注解時(shí)生效。
  • bean:當(dāng)調(diào)用的方法是指定的bean的方法時(shí)生效。

其實(shí)execution表示式的定義方式就是方法定義的全量方式

格式

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

括號中各個(gè)pattern分別表示:

  • 修飾符匹配(modifier-pattern?)
  • 返回值匹配(ret-type-pattern)可以為*表示任何返回值,全路徑的類名等
  • 類路徑匹配(declaring-type-pattern?)
  • 方法名匹配(name-pattern)可以指定方法名 或者 代表所有, set 代表以set開頭的所有方法
  • 參數(shù)匹配((param-pattern))可以指定具體的參數(shù)類型,多個(gè)參數(shù)間用“,”隔開,各個(gè)參數(shù)也可以用“”來表示匹配任意類型的參數(shù),如(String)表示匹配一個(gè)String參數(shù)的方法;(,String) 表示匹配有兩個(gè)參數(shù)的方法,第一個(gè)參數(shù)可以是任意類型,而第二個(gè)參數(shù)是String類型;可以用(…)表示零個(gè)或多個(gè)任意參數(shù)
  • 異常類型匹配(throws-pattern?)

其中后面跟著“?”的是可選項(xiàng)

例子

1execution(* *(..))//表示匹配所有方法 2execution(public * com.savage.service.UserService.*(..))//表示匹配com.savage.server.UserService中所有的公有方法 3execution(* com.savage.server..*.*(..))//表示匹配com.savage.server包及其子包下的所有方法

*> 最靠近(…)的為方法名,靠近.(…))的為類名或者接口名,如上例的JoinPointObjP2.(…))

參考:Spring AOP 中pointcut expression表達(dá)式解析及配置

方法參數(shù)匹配

args()
@args()

//參數(shù)帶有@MyMethodAnnotation標(biāo)注的方法. @args(com.elong.annotation.MyMethodAnnotation) //參數(shù)為String類型(運(yùn)行時(shí)決定)的方法. args(String)
當(dāng)前AOP代理對象類型匹配

this()

目標(biāo)類匹配

target()
@target()
within()
@within()

//pointcutexp包里的任意類. within(com.test.spring.aop.pointcutexp.*) //pointcutexp包和所有子包里的任意類. within(com.test.spring.aop.pointcutexp..*) //實(shí)現(xiàn)了MyInterface接口的所有類,如果MyInterface不是接口,限定MyInterface單個(gè)類. this(com.test.spring.aop.pointcutexp.MyInterface)

***> 當(dāng)一個(gè)實(shí)現(xiàn)了接口的類被AOP的時(shí)候,用getBean方法必須cast為接口類型,不能為該類的類型.

標(biāo)有此注解的方法匹配

@annotation()

//帶有@MyTypeAnnotation標(biāo)注的所有類的任意方法. @within(com.elong.annotation.MyTypeAnnotation) @target(com.elong.annotation.MyTypeAnnotation) //帶有@MyTypeAnnotation標(biāo)注的任意方法. @annotation(com.elong.annotation.MyTypeAnnotation)

***> @within和@target針對類的注解,@annotation是針對方法的注解

@Before("og()")
這種使用方式等同于以下方式,直接定義execution表達(dá)式使用
@Before("execution(* com.savage.aop.MessageSender.*(..))")

Pointcut定義時(shí),還可以使用&&、||、! 這三個(gè)運(yùn)算

@Pointcut("execution(* com.savage.aop.MessageSender.*(..))") private void logSender(){}@Pointcut("execution(* com.savage.aop.MessageReceiver.*(..))") private void logReceiver(){}@Pointcut("logSender() || logReceiver()") private void logMessage(){}

還可以將一些公用的Pointcut放到一個(gè)類中,以供整個(gè)應(yīng)用程序使用,如下:

package com.savage.aop;import org.aspectj.lang.annotation.*;public class Pointcuts {@Pointcut("execution(* *Message(..))")public void logMessage(){}@Pointcut("execution(* *Attachment(..))")public void logAttachment(){}@Pointcut("execution(* *Service.*(..))")public void auth(){} }

在使用上面定義Pointcut時(shí),指定完整的類名加上Pointcut簽名就可以了,如:

package com.savage.aop;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*;@Aspect public class LogBeforeAdvice { @Before("com.sagage.aop.Pointcuts.logMessage()") public void before(JoinPoint joinPoint) { System.out.println("Logging before " + joinPoint.getSignature().getName()); } }

也可以使用xml配置

<aop:config><aop:pointcut id="log" expression="execution(* com.savage.simplespring.bean.MessageSender.*(..))"/><aop:aspect id="logging" ref="logBeforeAdvice"><aop:before pointcut-ref="log" method="before"/><aop:after-returning pointcut-ref="log" method="afterReturning"/></aop:aspect> </aop:config> package com.ufgov.util.rest;/*** 記錄api訪問日志的切面*/ @Aspect public class ApiLogAspect{private static Logger logger = Logger.getLogger(ApiLogAspect.class);/*** 定義切入點(diǎn)*/@Pointcut("@annotation(ApiInf)")//這里就是表達(dá)式//Pointcut簽名public void controllerAspect() {}@Around("controllerAspect()")public Object around(ProceedingJoinPoint point) throws Throwable {// TODO somethingreturn point.proceed(); // 不調(diào)用point.proceed()不會(huì)執(zhí)行目標(biāo)方法}/*** 進(jìn)入方法之前處理*/@Before("controllerAspect()")public void doBefore() throws UnsupportedEncodingException{......}/*** 記錄返回信息*/@AfterReturning(pointcut="controllerAspect()",returning="ret")public void doAfterReturn(Object ret) {//對返回?cái)?shù)據(jù)進(jìn)行格式化處理,用于入庫}/*** 記錄發(fā)生的異常信息* @param e*/@AfterThrowing(value="controllerAspect()",throwing="e")public void doAfterThrow(Throwable e) {e.printStackTrace();......} }
在目標(biāo)方法上添加注解
@ApiInfo ....

總結(jié)

以上是生活随笔為你收集整理的AspectJ详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。