沉梦听雨的编程指南 沉梦听雨的编程指南
首页
  • 基础篇
  • 集合篇
  • 并发篇
  • JVM
  • 新特性
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 基础篇
  • MySql
  • Redis
  • 达梦数据库
  • Spring
  • SpringBoot
  • Mybatis
  • Shiro
  • 设计须知
  • UML画图
  • 权限校验
  • 设计模式
  • API网关
  • RPC
  • 消息队列
  • SpringCloud
  • 分布式事务
  • 云存储
  • 搜索引擎
  • 多媒体框架
  • 虚拟机
  • 开发工具篇
  • 工具库篇
  • 开发技巧篇
  • 工具类系列
  • 随笔
  • 前端环境搭建
  • HTML与CSS
  • JS学习
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • 脚手架搭建
  • 瑞吉外卖
  • 黑马点评
  • vue-blog
  • 沉梦接口开放平台
  • 用户中心
  • 聚合搜索平台
  • 仿12306项目
  • 壁纸小程序项目
  • RuoYi-Vue
  • 博客搭建
  • 网站收藏箱
  • 断墨寻径摘录
  • 费曼学习法
Github (opens new window)

沉梦听雨

时间是最好的浸渍剂,而沉淀是最好的提纯器🚀
首页
  • 基础篇
  • 集合篇
  • 并发篇
  • JVM
  • 新特性
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 基础篇
  • MySql
  • Redis
  • 达梦数据库
  • Spring
  • SpringBoot
  • Mybatis
  • Shiro
  • 设计须知
  • UML画图
  • 权限校验
  • 设计模式
  • API网关
  • RPC
  • 消息队列
  • SpringCloud
  • 分布式事务
  • 云存储
  • 搜索引擎
  • 多媒体框架
  • 虚拟机
  • 开发工具篇
  • 工具库篇
  • 开发技巧篇
  • 工具类系列
  • 随笔
  • 前端环境搭建
  • HTML与CSS
  • JS学习
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • 脚手架搭建
  • 瑞吉外卖
  • 黑马点评
  • vue-blog
  • 沉梦接口开放平台
  • 用户中心
  • 聚合搜索平台
  • 仿12306项目
  • 壁纸小程序项目
  • RuoYi-Vue
  • 博客搭建
  • 网站收藏箱
  • 断墨寻径摘录
  • 费曼学习法
Github (opens new window)
  • Spring

    • Spring基础小结
    • 聊聊Spring IoC 和 AOP
    • AOP实战
      • 常见注解
        • @Aspect
        • @Pointcut
        • @Before
        • @After
        • @AfterReturning
        • @AfterThrowing
        • @Around
      • 环绕通知是如何判定前后的?
        • 执行前(Before)
        • 执行后(After)
        • 异常处理
      • 学习参考
    • 元注解知识小结
    • SpringCache小记
    • 异步注解相关
    • ThreadPoolTaskExecutor与ThreadPoolExecutor的区别
    • 讲讲Spring事务
  • SpringBoot

  • Mybatis

  • Shiro

  • 常用框架
  • Spring
沉梦听雨
2024-04-01
目录

AOP实战

# AOP 实战

# 常见注解

# @Aspect

  • 用于定义一个切面,将横切逻辑封装在切面中。

  • 切面是包含切入点和通知的类。

  • 示例代码:

    @Aspect
    @Component
    public class LoggingAspect {
        // 切面类的实现
    }
    
    1
    2
    3
    4
    5

# @Pointcut

  • 用于定义一个切入点,指定在哪些连接点上应用切面逻辑。

  • 可以在多个通知中重复使用同一个切入点。

  • 示例代码:

    @Pointcut("execution(* com.example.service.*.*(..))")
    private void serviceLayer() {}
    
    1
    2

# @Before

  • 用于定义一个前置通知,在方法执行之前执行切面逻辑。

  • 在连接点之前执行。

  • 示例代码:

    @Before("serviceLayer()")
    public void beforeAdvice() {
        // 执行前置通知逻辑
    }
    
    1
    2
    3
    4

# @After

  • 用于定义一个后置通知,在方法执行之后执行切面逻辑(无论方法是否抛出异常)。

  • 在连接点之后执行。

  • 示例代码:

    @After("serviceLayer()")
    public void afterAdvice() {
        // 执行后置通知逻辑
    }
    
    1
    2
    3
    4

# @AfterReturning

  • 用于定义一个返回后通知,在方法正常返回后执行切面逻辑。

  • 只在方法正常返回时执行,在方法抛出异常时不执行。

  • 示例代码:

    @AfterReturning(pointcut = "serviceLayer()", returning = "result")
    public void afterReturningAdvice(Object result) {
        // 执行返回后通知逻辑
    }
    
    1
    2
    3
    4

# @AfterThrowing

  • 用于定义一个异常通知,在方法抛出异常后执行切面逻辑。

  • 只在方法抛出异常时执行,在方法正常返回时不执行。

  • 示例代码:

    @AfterThrowing(pointcut = "serviceLayer()", throwing = "exception")
    public void afterThrowingAdvice(Exception exception) {
        // 执行异常通知逻辑
    }
    
    1
    2
    3
    4

# @Around

  • 用于定义一个环绕通知,在方法执行前后执行切面逻辑,并控制方法的执行。

  • 在连接点之前和之后执行。

  • 示例代码:

    @Around("serviceLayer()")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        // 执行前置逻辑
        Object result = joinPoint.proceed(); // 执行被通知的方法
        // 执行后置逻辑
        return result;
    }
    
    1
    2
    3
    4
    5
    6
    7

# 环绕通知是如何判定前后的?

在使用 AOP 的环绕通知(@Around)时,你可以通过 ProceedingJoinPoint 对象的 proceed() 方法来决定是执行前还是执行后。

  • proceed() 方法的作用是:执行被通知(advice)的目标方法。

以下是如何控制执行时机的详细说明:

# 执行前(Before)

在调用 proceed() 方法之前,你可以执行任何你需要在目标方法执行之前的逻辑。这通常包括验证、设置上下文信息、记录日志等。例如:

public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
    // 执行前的逻辑,例如权限检查
    checkPermission(authCheck);

    try {
        // 继续执行目标方法
        return joinPoint.proceed();
    } catch (Throwable e) {
        // 异常处理逻辑
        handleException(e);
        throw e;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在这个例子中,checkPermission 方法会在目标方法执行前被调用,用于进行权限检查。如果权限检查通过,joinPoint.proceed() 会被调用,从而执行目标方法。

# 执行后(After)

目标方法的执行可以在 proceed() 方法调用后被认为是“执行后”。一旦 proceed() 方法被调用,目标方法就会开始执行。目标方法执行完成后,你可以在 proceed() 方法之后执行任何清理或后续操作。例如:

public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
    try {
        // 执行前的逻辑
        checkPermission(authCheck);
        // 执行目标方法
        return joinPoint.proceed();
    } catch (Throwable e) {
        // 异常处理逻辑
        handleException(e);
        throw e;
    } finally {
        // 执行后的逻辑,无论目标方法是否成功执行都会执行
        cleanupResources();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在这个例子中,cleanupResources 方法会在 proceed() 方法调用之后执行,无论目标方法是否成功执行。这使得 finally 块成为执行清理逻辑的理想位置。

# 异常处理

如果在目标方法执行过程中抛出异常,你可以在 catch 块中捕获并处理这些异常。这允许你在方法执行后进行异常处理,同时仍然可以在 finally 块中执行清理逻辑。

总结一下,通过控制 proceed() 方法的调用时机,你可以在目标方法执行前后执行自定义的逻辑。使用 AOP 的环绕通知提供了一种灵活的方式来在方法执行的不同阶段插入横切关注点。

# 学习参考

  • 8000字涵盖几乎所有的springboot注解以及详解!! - 掘金 (juejin.cn) (opens new window)
上次更新: 2024/9/25 11:16:13
聊聊Spring IoC 和 AOP
元注解知识小结

← 聊聊Spring IoC 和 AOP 元注解知识小结→

Theme by Vdoing | Copyright © 2023-2025 沉梦听雨 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式