【Spring】spring aop中pointcut表达式完整版

柔情只为你懂 2022-12-10 07:19 233阅读 0赞

spring aop中pointcut表达式完整版

本文主要介绍spring aop中9种切入点表达式的写法

  1. execute
  2. within
  3. this
  4. target
  5. args
  6. @target
  7. @within
  8. @annotation
  9. @args

0. 示例代码git地址

https://gitee.com/likun_557/spring-aop-demo

1.execute表达式

拦截任意公共方法

  1. execution(public * *(..))

拦截以set开头的任意方法

  1. execution(* set*(..))

拦截类或者接口中的方法

  1. execution(* com.xyz.service.AccountService.*(..))

拦截AccountService(类、接口)中定义的所有方法

拦截包中定义的方法,不包含子包中的方法

  1. execution(* com.xyz.service.*.*(..))

拦截com.xyz.service包中所有类中任意方法,不包含子包中的类

拦截包或者子包中定义的方法

  1. execution(* com.xyz.service..*.*(..))

拦截com.xyz.service包或者子包中定义的所有方法

2.within表达式

表达式格式:包名.* 或者 包名…*

拦截包中任意方法,不包含子包中的方法

  1. within(com.xyz.service.*)

拦截service包中任意类的任意方法

拦截包或者子包中定义的方法

  1. within(com.xyz.service..*)

拦截service包及子包中任意类的任意方法

3.this表达式

代理对象为指定的类型会被拦截

目标对象使用aop之后生成的代理对象必须是指定的类型才会被拦截,注意是目标对象被代理之后生成的代理对象和指定的类型匹配才会被拦截

  1. this(com.xyz.service.AccountService)

示例

this表达式的使用,可能不是很好理解,用示例说明一下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.1.4.RELEASE</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.ms</groupId>
  12. <artifactId>spring-aop-demo</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>spring-aop-demo</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>1.8</java.version>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-aop</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.projectlombok</groupId>
  26. <artifactId>lombok</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-test</artifactId>
  31. <scope>test</scope>
  32. </dependency>
  33. </dependencies>
  34. <build>
  35. <plugins>
  36. <plugin>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-maven-plugin</artifactId>
  39. </plugin>
  40. </plugins>
  41. </build>
  42. </project>
  43. package com.ms.aop.jthis.demo1;
  44. public interface IService {
  45. void m1();
  46. }
  47. package com.ms.aop.jthis.demo1;
  48. import lombok.extern.slf4j.Slf4j;
  49. import org.springframework.stereotype.Component;
  50. @Slf4j
  51. @Component
  52. public class ServiceImpl implements IService {
  53. @Override
  54. public void m1() {
  55. log.info("切入点this测试!");
  56. }
  57. }
  58. package com.ms.aop.jthis.demo1;
  59. import lombok.extern.slf4j.Slf4j;
  60. import org.aspectj.lang.ProceedingJoinPoint;
  61. import org.aspectj.lang.annotation.Around;
  62. import org.aspectj.lang.annotation.Aspect;
  63. import org.aspectj.lang.annotation.Pointcut;
  64. import org.springframework.stereotype.Component;
  65. @Aspect
  66. @Component
  67. @Slf4j
  68. public class Interceptor1 {
  69. @Pointcut("this(com.ms.aop.jthis.demo1.ServiceImpl)")
  70. public void pointcut() {
  71. }
  72. @Around("pointcut()")
  73. public Object invoke(ProceedingJoinPoint invocation) throws Throwable {
  74. log.info("方法执行之前");
  75. Object result = invocation.proceed();
  76. log.info("方法执行完毕");
  77. return result;
  78. }
  79. }
  80. package com.ms.aop.jthis.demo1;
  81. import lombok.extern.slf4j.Slf4j;
  82. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  83. import org.springframework.context.annotation.ComponentScan;
  84. import org.springframework.context.annotation.EnableAspectJAutoProxy;
  85. @ComponentScan(basePackageClasses = {Client.class})
  86. @EnableAspectJAutoProxy
  87. @Slf4j
  88. public class Client {
  89. public static void main(String[] args) {
  90. AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Client.class);
  91. IService service = annotationConfigApplicationContext.getBean(IService.class);
  92. service.m1();
  93. log.info("{}", service instanceof ServiceImpl);
  94. }
  95. }

执行结果

  1. 10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.ServiceImpl - 切入点this测试!
  2. 10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.Client - false
  1. @EnableAspectJAutoProxy:表示若spring创建的对象如果实现了接口,默认使用jdk动态代理,如果没有实现接口,使用cglib创建代理对象
  2. 所以 service 是使用jdk动态代理生成的对象,service instanceof ServiceImplfalse
  3. @Pointcut(“this(com.ms.aop.jthis.demo1.ServiceImpl)”)表示被spring代理之后生成的对象必须为com.ms.aop.jthis.demo1.ServiceImpl才会被拦截,但是service不是ServiceImpl类型的对象了,所以不会被拦截
  4. 修改代码

    1. @EnableAspectJAutoProxy(proxyTargetClass = true)
    • 1

    proxyTargetClass=true表示使用cglib来生成代理对象

    执行结果:

    1. 10:34:50.736 [main] INFO com.ms.aop.jthis.demo1.Interceptor1 - 方法执行之前
    2. 10:34:50.755 [main] INFO com.ms.aop.jthis.demo1.ServiceImpl - 切入点this测试!
    3. 10:34:50.756 [main] INFO com.ms.aop.jthis.demo1.Interceptor1 - 方法执行完毕
    4. 10:34:50.756 [main] INFO com.ms.aop.jthis.demo1.Client - true

    service 为 ServiceImpl类型的对象,所以会被拦截

4.target表达式

目标对象为指定的类型被拦截

  1. target(com.xyz.service.AccountService)

目标对象为AccountService类型的会被代理

示例

  1. package com.ms.aop.target;
  2. public interface IService {
  3. void m1();
  4. }
  5. package com.ms.aop.target;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.springframework.stereotype.Component;
  8. @Slf4j
  9. @Component
  10. public class ServiceImpl implements IService {
  11. @Override
  12. public void m1() {
  13. log.info("切入点target测试!");
  14. }
  15. }
  16. package com.ms.aop.target;
  17. import lombok.extern.slf4j.Slf4j;
  18. import org.aspectj.lang.ProceedingJoinPoint;
  19. import org.aspectj.lang.annotation.Around;
  20. import org.aspectj.lang.annotation.Aspect;
  21. import org.aspectj.lang.annotation.Pointcut;
  22. import org.springframework.stereotype.Component;
  23. @Aspect
  24. @Component
  25. @Slf4j
  26. public class Interceptor1 {
  27. @Pointcut("target(com.ms.aop.target.ServiceImpl)")
  28. public void pointcut() {
  29. }
  30. @Around("pointcut()")
  31. public Object invoke(ProceedingJoinPoint invocation) throws Throwable {
  32. log.info("方法执行之前");
  33. Object result = invocation.proceed();
  34. log.info("方法执行完毕");
  35. return result;
  36. }
  37. }
  38. package com.ms.aop.target;
  39. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  40. import org.springframework.context.annotation.ComponentScan;
  41. import org.springframework.context.annotation.EnableAspectJAutoProxy;
  42. @ComponentScan(basePackageClasses = {Client.class})
  43. @EnableAspectJAutoProxy
  44. public class Client {
  45. public static void main(String[] args) {
  46. AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Client.class);
  47. IService service = annotationConfigApplicationContext.getBean(IService.class);
  48. service.m1();
  49. }
  50. }

执行结果:

  1. 10:49:01.674 [main] INFO com.ms.aop.target.Interceptor1 - 方法执行之前
  2. 10:49:01.674 [main] INFO com.ms.aop.target.ServiceImpl - 切入点target测试!
  3. 10:49:01.674 [main] INFO com.ms.aop.target.Interceptor1 - 方法执行完毕

this 和 target 的不同点

  1. this作用于代理对象,target作用于目标对象
  2. this表示目标对象被代理之后生成的代理对象和指定的类型匹配会被拦截,匹配的是代理对象
  3. target表示目标对象和指定的类型匹配会被拦截,匹配的是目标对象

5.args 表达式

匹配方法中的参数

  1. @Pointcut("args(com.ms.aop.args.demo1.UserModel)")

匹配只有一个参数,且类型为com.ms.aop.args.demo1.UserModel

匹配多个参数

  1. args(type1,type2,typeN)

匹配任意多个参数

  1. @Pointcut("args(com.ms.aop.args.demo1.UserModel,..)")

匹配第一个参数类型为com.ms.aop.args.demo1.UserModel的所有方法, .. 表示任意个参数

6.@target表达式

匹配的目标对象的类有一个指定的注解

  1. @target(com.ms.aop.jtarget.Annotation1)

目标对象中包含com.ms.aop.jtarget.Annotation1注解,调用该目标对象的任意方法都会被拦截

7.@within表达式

指定匹配必须包含某个注解的类里的所有连接点

  1. @within(com.ms.aop.jwithin.Annotation1)

声明有com.ms.aop.jwithin.Annotation1注解的类中的所有方法都会被拦截

@target 和 @within 的不同点

  1. @target(注解A):判断被调用的目标对象中是否声明了注解A,如果有,会被拦截
  2. @within(注解A): 判断被调用的方法所属的类中是否声明了注解A,如果有,会被拦截
  3. @target关注的是被调用的对象,@within关注的是调用的方法所在的类

8.@annotation表达式

匹配有指定注解的方法(注解作用在方法上面)

  1. @annotation(com.ms.aop.jannotation.demo2.Annotation1)

被调用的方法包含指定的注解

9.@args表达式

方法参数所属的类型上有指定的注解,被匹配

注意:是方法参数所属的类型上有指定的注解,不是方法参数中有注解

  • 匹配1个参数,且第1个参数所属的类中有Anno1注解

    @args(com.ms.aop.jargs.demo1.Anno1)

  • 匹配多个参数,且多个参数所属的类型上都有指定的注解

    @args(com.ms.aop.jargs.demo1.Anno1,com.ms.aop.jargs.demo1.Anno2)

  • 匹配多个参数,且第一个参数所属的类中有Anno1注解

    @args(com.ms.aop.jargs.demo2.Anno1,..)

参考地址:https://blog.csdn.net/likun557/article/details/89405031

https://my.oschina.net/u/2278977/blog/799786

发表评论

表情:
评论列表 (有 0 条评论,233人围观)

还没有评论,来说两句吧...

相关阅读