首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么JoinPoint或ProceedingJoinPoint的对象可以调用方法?

基础概念

JoinPointProceedingJoinPoint 是 Spring AOP(面向切面编程)中的两个核心接口。它们用于在方法执行前后插入额外的逻辑(如日志记录、事务管理、权限检查等)。

  • JoinPoint:表示程序执行过程中的一个点,通常是一个方法的执行点。它提供了访问当前连接点的方法和目标对象的信息。
  • ProceedingJoinPoint:继承自 JoinPoint,它允许在切面中控制目标方法的执行。通过调用 proceed() 方法,可以继续执行目标方法。

相关优势

  1. 解耦:通过 AOP,可以将横切关注点(如日志记录、事务管理)从业务逻辑中分离出来,使代码更加清晰和模块化。
  2. 可维护性:横切关注点的变化不会影响到业务逻辑代码,提高了代码的可维护性。
  3. 可重用性:切面可以跨多个模块或项目重用,减少了重复代码。

类型

  • 静态切面:在编译时织入,通常通过注解或 XML 配置实现。
  • 动态切面:在运行时织入,通常通过代理机制实现。

应用场景

  • 日志记录:在方法执行前后记录日志。
  • 事务管理:在方法执行前后开启和提交事务。
  • 权限检查:在执行方法前检查用户权限。
  • 性能监控:记录方法的执行时间。

为什么 JoinPointProceedingJoinPoint 的对象可以调用方法?

JoinPointProceedingJoinPoint 是 Spring AOP 框架提供的接口,它们封装了目标方法的信息和调用上下文。通过这些接口,可以在切面中访问和操作目标方法。

  • JoinPoint:提供了访问目标对象和方法签名等信息的方法,如 getTarget()getSignature() 等。
  • ProceedingJoinPoint:继承自 JoinPoint,并提供了 proceed() 方法,该方法允许切面控制目标方法的执行。

示例代码

以下是一个简单的示例,展示了如何在切面中使用 ProceedingJoinPoint 来控制目标方法的执行:

代码语言:txt
复制
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    @Around("execution(* com.example.service.*.*(..))")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();

        Object proceed = joinPoint.proceed();

        long executionTime = System.currentTimeMillis() - start;

        System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");
        return proceed;
    }
}

参考链接

通过上述解释和示例代码,你应该能够理解 JoinPointProceedingJoinPoint 的基本概念、优势、类型、应用场景以及它们如何调用方法。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

写了个牛逼的日志切面,甩锅更方便了!

入参出错导致接口调试失败问题在联调中出现很多次,因此就想写一个请求日志切面把入参信息打印一下,同时协议层调用服务层接口名称对不上也出现了几次,通过请求日志切面就可以知道上层是否有没有发起调用,方便前后端甩锅还能拿出证据...().getDeclaringTypeName(), joinPoint.getSignature().getName()); } 在进入Controller方法前,打印出调用方IP、请求URL、HTTP...请求类型、调用的方法名 使用@Around打印进入控制层的入参 @Around("requestServer()") public Object doAround(ProceedingJoinPoint...,因此需要手动拼接一下参数名,同时对文件对象进行了特殊处理,只需获取文件名即可 @After方法调用后执行 @After("requestServer()") public void doAfter(JoinPoint...,再序列化打印对象 打印序列化对象结果而不是直接打印对象是因为序列化有更直观、更清晰,同时可以借助在线解析工具对结果进行解析 ?

41630

为什么start方法不能重复调用?而run方法却可以?

方法 thread2.start(); } 以上程序的执行结果如下: 从上述结果可以看出,二者调用之后的执行效果都是一样,都可以成功执行任务。...start 方法 thread2.start(); } 以上程序的执行结果如下: 从上述结果我们可以看出:当调用 run 方法时,其实是调用当前主程序 main 来执行方法体的;而调用...区别3 因为 run 方法是普通方法,而普通方法是可以被多次调用的,所以 run 方法可以被调用多次;而 start 方法是创建新线程来执行任务,因为线程只能被创建一次,所以它们的第三个区别是:run...方法可以被调用多次,而 start 方法只能被调用一次。...为什么start不能被重复调用?

73210
  • 写了个牛逼的日志切面,甩锅更方便了!

    ().getDeclaringTypeName(), joinPoint.getSignature().getName()); } 在进入 Controller 方法前,打印出调用方 IP...、请求 URL、HTTP 请求类型、调用的方法名 使用 @Around 打印进入控制层的入参 @Around("requestServer()") public Object doAround(ProceedingJoinPoint...,因此需要手动拼接一下参数名,同时对文件对象进行了特殊处理,只需获取文件名即可 @After 方法调用后执行 @After("requestServer()") public void doAfter...,再序列化打印对象 打印序列化对象结果而不是直接打印对象是因为序列化有更直观、更清晰,同时可以借助在线解析工具对结果进行解析 ?...推荐使用 log4j2,为什么推荐使用 log4j2 可以看下这篇文章:日志框架,选择 Logback Or Log4j2? log4j2 也是可以配合 MDC 一起使用的 ?

    1.8K31

    写了个牛逼的日志切面,甩锅更方便了!

    ().getDeclaringTypeName(), joinPoint.getSignature().getName()); } 在进入 Controller 方法前,打印出调用方 IP...、请求 URL、HTTP 请求类型、调用的方法名 使用 @Around 打印进入控制层的入参 @Around("requestServer()") public Object doAround(ProceedingJoinPoint...,因此需要手动拼接一下参数名,同时对文件对象进行了特殊处理,只需获取文件名即可 @After 方法调用后执行 @After("requestServer()") public void doAfter...写更健壮的代码 解决日志串行的问题只要将多行打印信息合并为一行就可以了,因此构造一个对象 RequestInfo.java @Data public class RequestInfo {...,再序列化打印对象 打印序列化对象结果而不是直接打印对象是因为序列化有更直观、更清晰,同时可以借助在线解析工具对结果进行解析 是不是还不错 在解决高并发下请求串行问题的同时添加了对异常请求信息的打印,

    59330

    Spring AOP 实践指南

    它提供了访问连接点的信息,如目标对象、方法签名、方法参数等。通过JoinPoint参数,可以获取有关当前正在执行的连接点的信息。...它提供了与JoinPoint相同的信息,但是可以用于获取连接点所在的类或切面的信息。 这些参数可以根据需要选择性地在通知方法中使用,以获取关于连接点和方法的相关信息。...默认情况下,Spring AOP 使用基于代理的 AOP,其中代理对象包装了目标对象,并在方法调用时执行切面逻辑。代理可以通过 JDK 动态代理或 CGLIB 生成。...但在使用环绕通知时,需要确保调用 ProceedingJoinPoint 对象的 proceed() 方法,以继续执行目标方法。否则,目标方法将被阻止执行。...Spring AOP 的限制: Spring AOP 只能应用于 Spring 容器管理的 bean 上。它无法拦截自调用的方法、静态方法或无法通过 Spring 容器管理的对象。

    10610

    【Java】已解决:org.springframework.aop.AopInvocationException

    该错误通常发生在尝试调用被代理的方法时,无法正确处理方法调用或方法本身存在问题。 问题场景 假设我们在开发一个Spring Boot项目时,使用AOP来记录方法的执行时间。...类型错误 如果在切面代码中未正确处理返回值的类型,可能导致AopInvocationException错误。例如,如果代理对象的方法返回类型与实际方法返回类型不匹配,则可能引发该异常。 2....数据类型不匹配 切面中的方法调用过程中,如果参数类型不匹配,或者在拦截方法时未正确处理参数类型,也可能引发此异常。 3....五、注意事项 正确调用ProceedingJoinPoint.proceed()方法:在使用AOP时,确保在切面中正确调用joinPoint.proceed()方法,以执行被代理的方法。...检查方法返回类型:确保切面中的返回类型与目标方法的返回类型一致,以避免类型不匹配的问题。 注意方法的访问修饰符:确保目标方法的访问修饰符允许切面访问和调用。

    11610

    AOP的设计与实现

    前置切面,在方法执行之前被调用 Around 环绕切面,可以在切面内部执行具体的方法,因此可以在具体方法执行前后添加自己需要的东西 After 后置切面,在方法执行完成之后被调用 基本功能 上面基础的三中切面支持...一个方法上可以被多个切面拦截(即一个方法可以同时对应多个Before,After,Around切面) 切面执行的先后顺序(一般而言,before优先around优先after) 被切的方法只能执行一遍...辅助类 实现AOP,肯定少不了代理,因此我们需要定义一个类,来包装执行方法相关的信息,用于传递给各个切面类中的方法 JoinPoint 包含实际对象,执行方法,参数 @Data public class...方法中,可以查询被切的方法基本信息(如方法签名,参数回信息,返回对象等) @Data public class BeforeProcess implements IAopProcess { /...,不过只有第一个around切面中是真的执行了具体方法调用,后面的around切面都是直接使用了第一个around执行后的结果(直接看ProceedingJoinPoint源码就知道了) AroundProcess

    92270

    调用内部或私有方法的N种方法

    非公开的类型或者方法被“隐藏”在程序集内部,本就不希望从外部访问,但是有时候调用一个内部或者私有方法可能是唯一的“救命稻草”,这篇文章列出了几种具体的实现方式。...以如下这个Foobar类型为例,它具有一个内部属性InternalValue,我们来看看有多少种方式可以从外部获取一个Foobar对象的InternalValue属性值。...由于返回值实际上是通过InternalValue属性的Get方法获得的,而表示方法的MethodInfo类型具有一个CreateDelegate方法,我们可以采用如下的方式利用InternalValue...在如下的代码中,我们创建了一个DynamicMethod类型表示的动态方法,以IL Emit的方式利用IL指令Call完成了针对InternalValue属性的Get方法的调用。...(calli) 了解IL的朋友应该知道,方法调用涉及的IL治理有三个(Call、Callvir和Calli)。

    21920

    Spring AOP到底是什么?

    利用容器管理所有的框架、业务对象,我们可以做到: 无侵入调整对象的关系 无侵入地随时调整对象的属性 实现对象的替换 这使得框架开发者在后续实现一些扩展就很容易。 什么是AOP?...例如,一个简单的缓存aspect可以返回一个值从缓存(如果它有)或调用procedd如果它没有。请注意,可以多次调用procedd,或者根本不在around advice的主体内调用,这都是合法的。...在通知的方法体中,调用 proceed() 会导致基础方法运行。 proceed() 也可以在Object[]中传递。数组中的值在进行时用作方法执行的参数。...Access to the Current JoinPoint 任何通知方法都可能声明类型org.aspectj.lang.JoinPoint 的参数(请注意,围绕建议需要申报类型’继续JoinPoint...JoinPoint 接口提供了许多有用的方法: getArgs() 返回方法的参数 getThis() 返回代理对象 getTarget() 返回目标对象 getSignature() Returns

    42420

    Spring-AOP思想

    [] interfaces = new Class[]{ArithmeticCalculator.class}; //当调用代理对象其中的方法时,该执行的代码 InvocationHandler...如果某方法调用前,调用后,方法抛出异常后。连接点由两个 信息确定:方法表示的程序执行点;相对点表示的方位。 切点: 每个类都拥有多个连接点。AOP通过切点定位到特定的连接点。...*(int, int))") 1 可以在声明的通知方法中声明一个类型为JoinPoint的参数,然后就能访问链接细节,如方法名称和参数。...+ " end with: " + result); } /** * 在方法出现异常时,会执行的代码 * 可以访问到异常对象,且可以指定出现特定异常时在执行通知代码...类型的参数 * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法 * 环绕通知必须有返回值,且返回值为目标方法的返回值

    26920

    业务系统 hystrix 实际应用

    第三方客户就是一个“黑匣子”,其中实施细节被隐藏,并且可以随时更改,网络或资源配置对于每个客户端库都是不同的,通常难以监视和 更改。 通过的故障包括: 网络连接失败或降级。 服务和服务器失败或变慢。...新的库或服务部署会改变行为或性能特征。 客户端库有错误。 所有这些都代表需要隔离和管理的故障和延迟,以便单个故障依赖关系不能导致整个应用程序或系统的故障。...主要有以下几点: 合理分配资源,把给资源分配的控制权交给用户,某一个依赖的故障不会影响到其他的依赖调用,访问资源也不受影响。 可以方便的指定调用策略,比如超时异常,熔断处理。...当一个失败的依赖再次变成可用时,线程池将清理,并立即恢复可用,而不是一个长时间的恢复。 可以完全模拟异步调用,方便异步编程。 使用线程池,可以有效的进行实时监控、统计和封装。...了,为什么呢?

    25710

    Spring5深入浅出篇:基于注解实现的AOP

    Spring5深入浅出篇:基于注解实现的AOP基于注解的AOP编程的开发步骤原始对象 额外功能 切⼊点 组装切⾯ 可以发现其实1,2,3最终目的就是为了去组装切面,其实这里和我们传统开发aop的步骤是一样的...{ //这里通过注解的方式定义切入点表达式 @Around("execution(* login(..))") public Object arround(ProceedingJoinPoint joinPoint...的方式来代表原始方法执行,而是ProceedingJoinPoint Object ret = joinPoint.proceed(); return ret; } //可以明显发现这里写了重复的代码...MethodInvocation的方式来代表原始方法执行,而是ProceedingJoinPoint Object ret = joinPoint.proceed(); return ret; } }...JDK 通过实现接⼝ 做新的实现类⽅式 创建代理对象2. Cglib通过继承⽗类 做新的⼦类 创建代理对象默认情况 AOP编程 底层应⽤JDK动态代理创建⽅式如果切换Cglib 1.

    18410

    Spring Boot 3 集成 Spring AOP实现系统日志记录

    JoinPoint主要用于获取连接点的信息,如方法名、参数、目标对象等,但不能控制方法的执行。...ProceedingJoinPoint:是JoinPoint的子接口,除了能获取连接点的信息外,还能控制方法的执行。...ProceedingJoinPoint:主要用于环绕通知,因为它提供了proceed()方法来继续执行原始方法。在环绕通知中,你可以在执行原始方法前后添加额外的逻辑。...在Spring AOP中,异常通知(@AfterThrowing)用于在目标方法抛出异常时执行的通知,它通常接收一个JoinPoint对象来获取连接点的信息,但不能接收ProceedingJoinPoint...只有环绕通知(@Around)可以接收ProceedingJoinPoint对象,该对象提供了继续执行原始方法的能力(通过调用proceed()方法),并且可以在方法执行前后添加额外的逻辑,包括异常处理

    11010

    Spring5系列(十一) | 基于注解的AOP编程

    原因就是login方法是用this调用的,获得的并不是代理对象所以不会执行对应的额外功能。相当于是直接调用了原始类中的方法。...如果此时让login方法也带上额外功能该怎么办呢,就是我们要通过代理对象去调用login方法。...这个时候就可以用我们之前文章中讲到的ApplicationContextAware来实现,把工厂注入进来,通过工厂去获取对象调用就可以了。...login方法,---核心功能,切面功能不执行 // 设计目的是: 调用代理对象的login方法 this.login("abc", "123456"); //获取代理对象...,只有最外层方法才是加入额外功能的,内部方法通过普通方式调用,都是调用原始方法,如果想让内层的方法也调用代理对象的方法,就要通过ApplicationContextAware接口,获取现有工厂 ,进而获得代理对象

    25810

    Spring AOP到底是什么?

    利用容器管理所有的框架、业务对象,我们可以做到: 无侵入调整对象的关系 无侵入地随时调整对象的属性 实现对象的替换 这使得框架开发者在后续实现一些扩展就很容易。 什么是AOP?...例如,一个简单的缓存aspect可以返回一个值从缓存(如果它有)或调用procedd如果它没有。请注意,可以多次调用procedd,或者根本不在around advice的主体内调用,这都是合法的。...在通知的方法体中,调用 proceed() 会导致基础方法运行。 proceed() 也可以在Object[]中传递。数组中的值在进行时用作方法执行的参数。...Access to the Current JoinPoint 任何通知方法都可能声明类型org.aspectj.lang.JoinPoint 的参数(请注意,围绕建议需要申报类型’继续JoinPoint...JoinPoint 接口提供了许多有用的方法: getArgs() 返回方法的参数 getThis() 返回代理对象 getTarget() 返回目标对象 getSignature() Returns

    15420

    创建子类对象时,父类构造函数中调用被子类重写的方法为什么调用的是子类的方法?

    A对象的时候父类会调用子类方法?...但是:创建B对象父类会调用父类的方法? 答案: 当子类被加载到内存方法区后,会继续加载父类到内存中。...如果,子类重写了父类的方法,子类的方法引用会指向子类的方法,否则子类的方法引用会指向父类的方法引用。 如果子类重载了父类方法,则子类重载方法引用还指向子类方法。...如果子类方法没有重写也没有重载父类方法,则方法引用会指向父类方法。 当子类对象创建时,会先行调用父类的构造方法(构造方法也是方法),虚拟机会在子类方法区寻找该方法并运行。...其结果是当编译的时候,父类构造方法调用的方法的参数已经强制转换为符合父类方法的参数了。 上边代码在编译前已经转换为下面这个样子的了。

    6.2K10
    领券