SpringAOP中@annotation与execution的深度示例对比分析

 更新时间:2025年08月06日 11:19:39   作者:bemyrunningdog  
Spring AOP中@annotation通过注解标记方法,适合定制化横切逻辑;execution基于方法签名匹配,用于通用功能增强,两者互补,根据需求选择,本文给大家介绍SpringAOP中@annotation与execution的深度示例对比分析,感兴趣的朋友一起看看吧

在 Spring AOP 中,@annotationexecution 是两种常用的切点表达式(Pointcut Expression),用于定义哪些方法需要被切面(Aspect)拦截。它们的设计目的、匹配规则和适用场景有显著区别,以下从核心机制、语法、应用场景和示例进行对比分析:

🔍 ​一、核心概念与机制​

1. ​**@annotation表达式**​

  • 作用​:匹配带有特定注解的方法
  • 原理​:基于方法上的注解标记进行拦截,与方法的签名(类名、方法名等)无关。
  • 适用场景​:
    • 需要为特定功能​(如日志、权限校验)标记方法时。
    • 需通过注解传递元数据(例如 @Permission(role="admin"))。
  • 优点​:灵活性高,与业务逻辑解耦,适合自定义横切关注点。
  • 缺点​:需显式在方法上添加注解,无法批量匹配无注解的方法。

2. ​**execution表达式**​

  • 作用​:通过方法签名​(返回值、包名、类名、方法名、参数类型)匹配方法。
  • 原理​:基于方法的结构特征拦截,无需方法添加额外注解。
  • 适用场景​:
    • 批量拦截特定包/类下的所有方法​(如 com.example.service.*.*(..))。
    • 按命名规范匹配方法(如所有 update* 开头的方法)。
  • 优点​:无需修改代码,适合通用功能(如接口耗时统计)。
  • 缺点​:表达式复杂,对无规则的方法难以精确匹配。

⚙️ ​二、语法详解​

1. ​**@annotation语法**​

@Before("@annotation(com.example.Loggable)")
public void logBefore(JoinPoint joinPoint) {
    // 通知逻辑
}
  • 参数​:注解的全限定类名(如 com.example.Loggable)。
  • 扩展​:可与自定义注解结合,实现动态控制(例如 @Loggable(level="DEBUG"))。

2. ​**execution语法**​

@Around("execution(* com.example.service.*.*(..))")
public Object monitor(ProceedingJoinPoint pjp) throws Throwable {
    // 环绕通知逻辑
}
  • 结构​:execution(修饰符? 返回值 包.类.?方法名(参数) 异常?)
    • *:通配任意元素(如返回值、单层包名)。
    • ..:通配多层包或任意参数(如 com..*.ServiceImpl 匹配 com 下所有子包的 ServiceImpl 类)。
  • 示例​:
    • 匹配 UserService 的所有方法:execution(* com.service.UserService.*(..))
    • 匹配所有 save 开头的方法:execution(* save*(..))

🧩 ​三、典型场景对比​

维度​**@annotation**​​**execution**​
匹配依据方法上的注解标记方法签名(包、类、方法名、参数等)
代码侵入性需在方法上添加注解无侵入,直接匹配方法结构
灵活性高(可通过注解参数定制逻辑)中(依赖方法命名和包结构)
适用案例- 权限校验(@RequireAuth
- 日志分级(@LogLevel("DEBUG")
- 接口耗时统计
- 全局事务管理
- 包级别异常处理
复杂匹配能力弱(仅依赖注解是否存在)强(支持通配符、逻辑运算符组合)

💻 ​四、代码示例​

1. ​**@annotation实现自定义日志**​

// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Loggable {}
// 切面类
@Aspect
@Component
public class LogAspect {
    @Before("@annotation(com.example.Loggable)")
    public void logMethodCall(JoinPoint jp) {
        System.out.println("Log: " + jp.getSignature().getName());
    }
}
// 业务方法使用
@Service
public class UserService {
    @Loggable
    public void createUser() { ... }
}

2. ​**execution实现方法耗时统计**​

@Aspect
@Component
public class TimeAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = pjp.proceed();
        long duration = System.currentTimeMillis() - start;
        System.out.println(pjp.getSignature() + " executed in " + duration + "ms");
        return result;
    }
}

✅ ​五、如何选择?​​

  • ​优先 @annotation​:
    当需要精细控制且逻辑与业务无关时(如权限、审计日志),通过注解实现解耦。
  • ​优先 execution​:
    需批量拦截​(如全局性能监控)或无法修改源码时,通过方法签名覆盖。
  • ​混合使用​:
    复杂场景可组合表达式,例如:
@Before("@annotation(com.example.Auth) && execution(* com.service.*.*(..))")

💎 ​总结​

  • ​**@annotation​:注解驱动,精准标记方法,适合高定制化横切逻辑**。
  • ​**execution​:结构驱动,无侵入匹配,适合通用功能增强**。
    两者本质是互补工具,实际开发中需根据侵入性容忍度匹配精度维护成本综合选择。

到此这篇关于SpringAOP中@annotation与execution的深度对比的文章就介绍到这了,更多相关springaop @annotation与execution内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java 方法泛型入参T和String的重载关系详解

    java 方法泛型入参T和String的重载关系详解

    这篇文章主要介绍了java 方法泛型入参T和String的重载关系详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • java中@NotBlank限制属性不能为空

    java中@NotBlank限制属性不能为空

    在实体类的对应属性上添 @NotBlank注解,可以实现对空置的限制,本文就来介绍一下java中@NotBlank限制属性不能为空,感兴趣的可以了解一下
    2024-01-01
  • Java中this关键字用法梳理详细讲解

    Java中this关键字用法梳理详细讲解

    this关键字是java常用的关键字,可用于任何实例方法内指向当前对象,也可指向对其调用当前方法的对象,下面这篇文章主要介绍了Java中this关键字用法梳理的相关资料,需要的朋友可以参考下
    2025-07-07
  • Java ThreadLocal详解_动力节点Java学院整理

    Java ThreadLocal详解_动力节点Java学院整理

    ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,本文会详细的介绍一下,有兴趣的可以了解一下
    2017-06-06
  • Spring Boot中的YML配置列表及应用小结

    Spring Boot中的YML配置列表及应用小结

    在Spring Boot中使用YAML进行列表的配置不仅简洁明了,还能提高代码的可读性和可维护性,这篇文章主要介绍了Spring Boot中的YML配置列表的详细解析,需要的朋友可以参考下
    2025-05-05
  • SpringBoot将Spring fox更换为Springdoc的方法详解

    SpringBoot将Spring fox更换为Springdoc的方法详解

    由于项目中使用Spring fox已经不维护更新了,代码扫描,扫出问题,需要将Spring fox更换为Spring Doc,所以本文给大家介绍了SpringBoot将Spring fox更换为Springdoc的方法,文中有相关的代码供大家参考,需要的朋友可以参考下
    2024-01-01
  • Java多线程 原子性操作类的使用

    Java多线程 原子性操作类的使用

    这篇文章主要介绍了Java多线程 原子性操作类的使用,在java5以后,我们接触到了线程原子性操作,也就是在修改时我们只需要保证它的那个瞬间是安全的即可,经过相应的包装后可以再处理对象的并发修改,本文总结一下Atomic系列的类的使用方法,下面一起进入文章了解详细内容
    2021-10-10
  • 如何使用java agent修改字节码并在springboot启动时自动生效

    如何使用java agent修改字节码并在springboot启动时自动生效

    本文介绍了JavaAgent的使用方法和在SpringBoot中的应用,JavaAgent可以通过修改类的字节码,实现对非Spring容器管理对象的AOP处理,演示了如何定义切面逻辑,实现接口mock,感兴趣的朋友跟随小编一起看看吧
    2024-10-10
  • Java 并发编程之ForkJoin框架

    Java 并发编程之ForkJoin框架

    这篇文章主要为大家介绍了Java ForkJoin框架,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助,希望能够给你带来帮助
    2021-11-11
  • Java实现超市会员管理系统

    Java实现超市会员管理系统

    这篇文章主要为大家详细介绍了Java实现超市会员管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03

最新评论