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利用for循环打印菱形的实例教程

    Java利用for循环打印菱形的实例教程

    这篇文章主要给大家介绍了关于Java利用for循环打印菱形的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • MyBatis树形结构查询的实现示例

    MyBatis树形结构查询的实现示例

    本文介绍了一种使用MyBatis进行树形结构查询的方法,通过构造临时表和内连接,实现了不同层级数据的一次性查询及映射,感兴趣的可以了解一下
    2025-11-11
  • 在SSM中配置了事务控制但没生效的问题

    在SSM中配置了事务控制但没生效的问题

    这篇文章主要介绍了在SSM中配置了事务控制但没生效的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • SpringBoot资源文件的存放位置设置方式

    SpringBoot资源文件的存放位置设置方式

    这篇文章主要介绍了SpringBoot资源文件的存放位置设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • SpringBoot AOP控制Redis自动缓存和更新的示例

    SpringBoot AOP控制Redis自动缓存和更新的示例

    今天小编就为大家分享一篇关于SpringBoot AOP控制Redis自动缓存和更新的示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Java生成Echarts表图的2种实现方案

    Java生成Echarts表图的2种实现方案

    这篇文章主要给大家介绍了关于Java生成Echarts表图的2种实现方案,ECharts是一款功能非常强大的JavaScript图表库,文中通过代码实例介绍的非常详细,需要的朋友可以参考下
    2023-09-09
  • Java 实现判定顺序表中是否包含某个元素(思路详解)

    Java 实现判定顺序表中是否包含某个元素(思路详解)

    这篇文章主要介绍了Java 实现判定顺序表中是否包含某个元素,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • Java使用组件编写窗口实现网上文件下载

    Java使用组件编写窗口实现网上文件下载

    这篇文章主要为大家详细介绍了Java使用组件编写窗口实现网上文件下载的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • 详解Java中字符流与字节流的区别

    详解Java中字符流与字节流的区别

    这篇文章主要为大家详细介绍了Java中字符流与字节流的区别,这两个的概念易混淆,今天就为大家进行详细区分,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • java 设计模型之单例模式详解

    java 设计模型之单例模式详解

    本文主要介绍了java 单例模式,单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在,希望能帮助有需要的同学
    2016-07-07

最新评论