Spring AOP切點表達式使用及說明
切點表達式
在Spring AOP中,連接點始終代表方法的執(zhí)行。切入點是與連接點匹配的謂詞,切入點表達語言是以編程方式描述切入點的方式。
切點表達式是除過AOP邏輯之外我們開發(fā)主要關注的東西,本小結對各種表達式作以說明,spring aop中目前有9種切入點表達式的寫法
execute
within
this
target
args
@target
@within
@annotation
@args
一、execute表達式
攔截任意公共方法
execution(public * *(..))
攔截以set開頭的任意方法
execution(* set*(..))
攔截類或者接口中的方法
攔截AccountService(類、接口)中定義的所有方法 execution(* com.xyz.service.AccountService.*(..))
攔截包中定義的方法,不包含子包中的方法
攔截com.xyz.service包中所有類中任意方法,**不包含**子包中的類 execution(* com.xyz.service.*.*(..))
攔截包或者子包中定義的方法
攔截com.xyz.service包或者子包中定義的所有方法 execution(* com.xyz.service..*.*(..))
二、within表達式
表達式格式:包名.* 或者 包名…*
攔截包中任意方法,不包含子包中的方法
攔截service包中任意類的任意方法 within(com.xyz.service.*)
攔截包或者子包中定義的方法
攔截service包及子包中任意類的任意方法 within(com.xyz.service..*)
三、this表達式
代理對象為指定的類型會被攔截
目標對象使用aop之后生成的代理對象必須是指定的類型才會被攔截,注意是目標對象被代理之后生成的代理對象和指定的類型匹配才會被攔截 this(com.xyz.service.AccountService)
this表達式的使用,可能不是很好理解,借用示例說明一下:
package com.ms.aop.jthis.demo1; ? public interface IService { void m1(); } package com.ms.aop.jthis.demo1; ? import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; ? @Slf4j @Component public class ServiceImpl implements IService { @Override public void m1() { log.info("切入點this測試!"); } } package com.ms.aop.jthis.demo1; ? import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component @Slf4j public class Interceptor1 { ? @Pointcut("this(com.ms.aop.jthis.demo1.ServiceImpl)") public void pointcut() { } ? @Around("pointcut()") public Object invoke(ProceedingJoinPoint invocation) throws Throwable { log.info("方法執(zhí)行之前"); Object result = invocation.proceed(); log.info("方法執(zhí)行完畢"); return result; } } package com.ms.aop.jthis.demo1; ? import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.EnableAspectJAutoProxy; ? @ComponentScan(basePackageClasses = {Client.class}) @EnableAspectJAutoProxy @Slf4j public class Client { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Client.class); IService service = annotationConfigApplicationContext.getBean(IService.class); service.m1(); log.info("{}", service instanceof ServiceImpl); } }
執(zhí)行結果
10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.ServiceImpl - 切入點this測試!
10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.Client - false
- @EnableAspectJAutoProxy:表示若spring創(chuàng)建的對象如果實現(xiàn)了接口,默認使用jdk動態(tài)代理,如果沒有實現(xiàn)接口,使用cglib創(chuàng)建代理對象 所以 service 是使用jdk動態(tài)代理生成的對象,service instanceof ServiceImpl 為 false
- @Pointcut(“this(com.ms.aop.jthis.demo1.ServiceImpl)”) 表示被spring代理之后生成的對象必須為com.ms.aop.jthis.demo1.ServiceImpl才會被攔截,但是service不是ServiceImpl類型的對象了【這是因為默認采用的JDK動態(tài)代理,所以AOP生成的是代理對象,因此也service就不是ServiceImpl類型的對象】,所以不會被攔截
修改代碼
@EnableAspectJAutoProxy(proxyTargetClass = true) proxyTargetClass=true表示強制使用cglib來生成代理對象
執(zhí)行結果:
10:34:50.755 [main] INFO com.ms.aop.jthis.demo1.ServiceImpl - 切入點this測試!
10:34:50.756 [main] INFO com.ms.aop.jthis.demo1.Interceptor1 - 方法執(zhí)行完畢
10:34:50.756 [main] INFO com.ms.aop.jthis.demo1.Client - true
service 為 ServiceImpl類型的對象,所以會被攔截,因為熟悉CGLIB理論知識的同學都知道,CGLIB生成的代理對象是源類型的子類,因此service肯定是ServiceImpl類型的對象了,因為多態(tài)屬于關系。
四、target表達式
目標對象為指定的類型被攔截
target(com.xyz.service.AccountService) 目標對象為AccountService類型的會被代理
this 和 target 的不同點
- this作用于代理對象,target作用于目標對象
- this表示目標對象被代理之后生成的代理對象和指定的類型匹配會被攔截,匹配的是代理對象
- target表示目標對象和指定的類型匹配會被攔截,匹配的是目標對象
五、args 表達式
匹配方法中的參數(shù)
匹配只有一個參數(shù),且類型為 com.ms.aop.args.demo1.UserModel@Pointcut("args(com.ms.aop.args.demo1.UserModel)")
- 匹配多個參數(shù) args(type1,type2,typeN)
匹配任意多個參數(shù)
匹配第一個參數(shù)類型為com.ms.aop.args.demo1.UserModel的所有方法, .. 表示任意個參數(shù) @Pointcut("args(com.ms.aop.args.demo1.UserModel,..)")
六、@target表達式
匹配的目標對象的類有一個指定的注解
目標對象中包含com.ms.aop.jtarget.Annotation1注解,調(diào)用該目標對象的任意方法都會被攔截 @target(com.ms.aop.jtarget.Annotation1)
七、@within表達式
指定匹配必須包含某個注解的類里的所有連接點
聲明有com.ms.aop.jwithin.Annotation1注解的類中的所有方法都會被攔截 ???????@within(com.ms.aop.jwithin.Annotation1)
@target 和 @within 的不同點
- @target(注解A):判斷被調(diào)用的目標對象中是否聲明了注解A,如果有,會被攔截
- @within(注解A): 判斷被調(diào)用的方法所屬的類中是否聲明了注解A,如果有,會被攔截
- @target關注的是被調(diào)用的對象,@within關注的是調(diào)用的方法所在的類
八、@annotation表達式
匹配有指定注解的方法(注解作用在方法上面)
@annotation(com.ms.aop.jannotation.demo2.Annotation1)
被調(diào)用的方法包含指定的注解
九、@args表達式
方法參數(shù)所屬的類型上有指定的注解,被匹配
注意:是方法參數(shù)所屬的類型上有指定的注解,不是方法參數(shù)中有注解
匹配1個參數(shù),且第1個參數(shù)所屬的類中有Anno1注解
- @args(com.ms.aop.jargs.demo1.Anno1)
- 匹配多個參數(shù),且多個參數(shù)所屬的類型上都有指定的注解
- @args(com.ms.aop.jargs.demo1.Anno1,com.ms.aop.jargs.demo1.Anno2)
- 匹配多個參數(shù),且第一個參數(shù)所屬的類中有Anno1注解
- @args(com.ms.aop.jargs.demo2.Anno1,…)
切點表達式組合
另外,可以使用&&、||、!、三種運算符來組合切點表達式,表示與或非的關系。
@Pointcut("@target(org.springframework.stereotype.Repository)") public void repositoryMethods() {} @Pointcut("execution(* *..create*(Long,..))") public void firstLongParamMethods() {} @Pointcut("repositoryMethods() && firstLongParamMethods()") public void entityCreationMethods() {}
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Java實現(xiàn)拖拽文件上傳dropzone.js的簡單使用示例代碼
本篇文章主要介紹了Java實現(xiàn)拖拽文件上傳dropzone.js的簡單使用示例代碼,具有一定的參考價值,有興趣的可以了解一下2017-07-07Java Swing null絕對布局的實現(xiàn)示例
這篇文章主要介紹了Java Swing null絕對布局的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12