Spring AOP常用类:ProceedingJoinPoint、JoinPoint

embedded/2024/11/27 5:03:27/

在说到Spring框架,我们往往对Spring MVC ,Spring Web更加熟悉。

Spring AOP也是Spring大家族中的一员。相比于机械的记忆,在实际做项目的过程中,我才真正的接触和应用到它,也理解了它的含义。

首先提到Spring AOP,就不得不说到AOP:面向切面编程。

关于它的定义有很多,这里无需赘述,总之在实际应用中,我们往往需要自己定义注解,编写切面类,比如下面的注解,我们要重写日志,以便于在控制台看到足够的信息。

自定义注解

java">package com.quanxiaoha.weblog.common.aspect;import java.lang.annotation.*;@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface ApiOperationLog {/*** API 功能描述** @return*/String description() default "";}

在这个注解里,设置了一个默认的description为""

注解有了,我们需要编写切面类:

java">@Aspect
@Component
@Slf4j
public class ApiOperationLogAspect {/** 以自定义 @ApiOperationLog 注解为切点,凡是添加 @ApiOperationLog 的方法,都会执行环绕中的代码 */@Pointcut("@annotation(com.quanxiaoha.weblog.common.aspect.ApiOperationLog)")public void apiOperationLog() {}/*** 环绕* @param joinPoint* @return* @throws Throwable*/@Around("apiOperationLog()")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {try {... ...(省略)// 获取被请求的类和方法String className = joinPoint.getTarget().getClass().getSimpleName();String methodName = joinPoint.getSignature().getName();... ...// 执行切点方法Object result = joinPoint.proceed();... ...return result;} finally {MDC.clear();}}
}

这个切面类仅作示例,且源代码为我跟做的项目的源码,因此这里隐藏了部分,仅留下一些框架作为讲解。

由于这个是环绕型的,所以我们在编写的时候需要选用ProceedingJoinPoint而不是JoinPoint

具体原因可以看方法体里的代码,首先要获取被请求的类和方法,然后执行一系列操作后还要继续执行注解方法joinPoint.proceed(),然后再进行一系列操作。

由此,我们能够看出它的特点,就是它可以控制目标方法继续执行

区别

ProceedingJoinPoint JoinPoint 都是 Spring AOP 中的接口,用于在切面编程中获取方法的相关信息。它们的区别主要在于功能上,尤其是在环绕通知(@Around)和其他通知(如前置通知、后置通知)中的使用方式。

JoinPoint 接口:

JoinPoint Spring AOP 中最基础的接口,它代表了目标方法执行的一个“连接点”。JoinPoint 提供了对方法签名、参数等基本信息的访问。

主要功能:

  • 获取目标方法的 签名(getSignature());
  • 获取目标方法的 参数(getArgs());
  • 获取目标方法的 目标类(getTarget());
  • 获取当前连接点的 方法名(getSignature().getName())。

使用场景:
JoinPoint 一般用于 前置通知、后置通知 或 异常通知 等。这些通知不需要控制目标方法的执行流程
示例:

java">@Around("execution(* com.example.service.*.*(..))")
public Object logAround(JoinPoint joinPoint) {// 获取方法名String methodName = joinPoint.getSignature().getName();// 获取参数Object[] args = joinPoint.getArgs();// 打印日志System.out.println("Method name: " + methodName);System.out.println("Arguments: " + Arrays.toString(args));return null;
}

ProceedingJoinPoint 接口:

ProceedingJoinPoint JoinPoint 子接口,提供了比 JoinPoint 更多的功能,特别是在环绕通知中,用于继续执行目标方法

主要区别:
继续执行目标方法:ProceedingJoinPoint 提供了一个proceed()方法,该方法用于在环绕通知中继续执行目标方法,并且可以传递新的参数。如果你使用的是 JoinPoint,就无法在通知中继续执行目标方法。
JoinPoint 相同的功能:ProceedingJoinPoint 继承了 JoinPoint 的所有基本功能,例如获取方法签名、方法参数等

使用场景:

  • ProceedingJoinPoint 主要用于 环绕通知,因为只有环绕通知需要对目标方法的执行进行控制。
    示例:
java">@Around("execution(* com.example.service.*.*(..))")
public Object logAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {// 获取方法名String methodName = proceedingJoinPoint.getSignature().getName();// 获取参数Object[] args = proceedingJoinPoint.getArgs();// 打印日志System.out.println("Method name: " + methodName);System.out.println("Arguments: " + Arrays.toString(args));// 执行目标方法Object result = proceedingJoinPoint.proceed();// 执行完毕后打印返回值System.out.println("Result: " + result);return result;
}

主要区别总结:

特性JoinPointProceedingJoinPoint
功能获取方法签名、参数等基本信息获取方法签名、参数等基本信息,并且能够控制目标方法的执行
通知类型用于前置通知、后置通知、异常通知等仅用于环绕通知
是否可以控制目标方法执行不可以可以,通过 proceed() 方法继续执行目标方法

http://www.ppmy.cn/embedded/140818.html

相关文章

突破Zustand的局限性:与React ContentAPI搭配使用

Zustand在状态管理中是非常适手的工具,在很多场景中我们都可以用它来解决复杂问题. 但是由于Zustand的设计理念,它仍然有一些限制,在这里用官网中的小demo举一个很简单的例子: import { create } from zustand type CountStore …

Docker pull镜像拉取失败

因为一些原因,很多镜像仓库拉取镜像失败,所以需要更换不同的镜像,这是2024/11/25测试可用的仓库。 标题1、 更换镜像仓库的地址,编辑daemon.json文件 vi /etc/docker/daemon.json标题2、然后将下面的镜像源放进去或替换掉都可以…

计算机网络socket编程(4)_TCP socket API 详解

个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 计算机网络socket编程(4)_TCP socket API 详解 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记,欢迎大家在评论区交流讨论&…

php 限制访问次数

php 限制访问次数 限制访问次数的php 文件提示 &#xff1a; 会生成一个 visits.json 文件 用来记录访问日志 并不是恶意文件需要指定正确的访问路径 <?php# 限制访问次数的php 文件 # 提示 &#xff1a; 会生成一个 visits.json 文件 用来记录访问日志 并不是恶意文件se…

Node.js的http模块:创建HTTP服务器、客户端示例

新书速览|Vue.jsNode.js全栈开发实战-CSDN博客 《Vue.jsNode.js全栈开发实战&#xff08;第2版&#xff09;&#xff08;Web前端技术丛书&#xff09;》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) 要使用http模块&#xff0c;只需要在文件中通过require(http)引入即可。…

Oracle-行列转化实际的工作应用

create table score_line ( sname varchar2(20) ,subject varchar2(20) ,score number(3) ); create table score_col ( sname varchar2(20) ,yuwen number ,shuxue number ,yingyu number ); -- 列转行 -- 方法1 union all select s.sname,‘数学’as subject,s.s…

STM32 RAM在Memory Map中被分为3个区域

型号为STM32F407ZET6&#xff0c;Memory Map如下&#xff1a; 可以看到Flash是完整的一块区域&#xff0c;而RAM却被分成了12KB 16KB 64KB 192KB的三块。 通过查阅资料可知这是ST在芯片设计时针对不同类型的变量做出的考虑&#xff0c;其中&#xff1a; 1.CCM SRAM&#x…

开源宝藏:Smart-Admin 重复提交防护的 AOP 切面实现详解

首先&#xff0c;说下重复提交问题&#xff0c;基本上解决方案&#xff0c;核心都是根据URL、参数、token等&#xff0c;有一个唯一值检验是否重复提交。 而下面这个是根据用户id&#xff0c;唯一值进行判定&#xff0c;使用两种缓存方式&#xff0c;redis和caffeine&#xff…