spring-reading./spring-aop/spring-aop-advice-afterRetu...
linlei dbbbe5d1f1 AfterReturningAdvice优化 2024-04-23 16:44:26 +08:00
..
src/main/java/com/xcs/spring MethodBeforeAdvice接口源码分析 2024-04-11 12:03:27 +08:00
README.md AfterReturningAdvice优化 2024-04-23 16:44:26 +08:00
pom.xml MethodBeforeAdvice接口源码分析 2024-04-11 12:03:27 +08:00

README.md

AfterReturningAdvice

一、基本信息

✒️ 作者 - Lex 📝 博客 - 掘金 📚 源码地址 - github

二、基本描述

AfterReturningAdvice接口是Spring AOP框架中的一个核心接口用于在目标方法执行后拦截并执行自定义逻辑。通过实现该接口的afterReturning方法,可以在目标方法成功返回结果后进行一些操作,如日志记录、性能监控等。

三、主要功能

  1. 日志记录

    • 记录目标方法的执行情况,如方法名称、参数值、返回结果等,以便跟踪应用程序的运行状态。
  2. 性能监控

    • 统计目标方法的执行时间,分析应用程序的性能瓶颈,优化程序性能。
  3. 缓存处理

    • 在方法返回结果后,将结果缓存起来,以提高后续相同请求的响应速度。
  4. 统一处理

    • 执行一些与业务逻辑无关的统一处理,如资源释放、清理等。

四、接口源码

AfterReturningAdvice接口主要用于在方法正常返回时执行后置通知。后置通知可以查看方法的返回值,但不能修改它,并且仅在方法正常返回时被调用,不会在抛出异常时被调用。该接口提供了一个afterReturning方法,在方法成功返回后进行回调,其中包含了返回值、被调用的方法、方法的参数以及方法调用的目标对象等信息。

/**
 * 后置返回通知仅在方法正常返回时被调用,如果抛出异常则不会被调用。这样的通知可以查看方法的返回值,但不能修改它。
 * 
 * 作者Rod Johnson
 * @see MethodBeforeAdvice
 * @see ThrowsAdvice
 */
public interface AfterReturningAdvice extends AfterAdvice {

    /**
     * 在给定方法成功返回后的回调。
     * @param returnValue 方法返回的值,如果有的话
     * @param method 被调用的方法
     * @param args 方法的参数
     * @param target 方法调用的目标对象。可能为{@code null}。
     * @throws Throwable 如果此对象希望中止调用。如果方法签名允许,将返回任何抛出的异常给调用者。否则,异常将被包装为运行时异常。
     */
    void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;

}

五、主要实现

  1. AspectJAfterReturningAdvice

    • 实现了返回后通知,使用 AspectJ 风格定义的通知,用于在目标方法成功执行并返回结果后执行额外的逻辑。

六、最佳实践

使用Spring AOP中的后置返回通知AfterReturningAdvice。首先创建了一个代理工厂ProxyFactory并指定目标对象MyService。然后创建了一个后置返回通知MyAfterReturningAdvice并添加到代理工厂中。接着通过代理工厂获取代理对象并调用代理对象的方法。

public class AfterReturningAdviceDemo {

    public static void main(String[] args) {
        // 创建代理工厂&创建目标对象
        ProxyFactory proxyFactory = new ProxyFactory(new MyService());
        // 创建通知
        proxyFactory.addAdvice(new MyAfterReturningAdvice());
        // 获取代理对象
        MyService proxy = (MyService) proxyFactory.getProxy();
        // 调用代理对象的方法
        proxy.doSomething();
    }
}

MyAfterReturningAdvice的类它实现了Spring AOP框架中的AfterReturningAdvice接口。在afterReturning方法中,当目标方法成功返回结果时,它将打印出目标方法的名称以及返回的值。

public class MyAfterReturningAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("After method " + method.getName() + " is called, returned value: " + returnValue);
    }
}

MyService 类是一个简单的服务类,其中包含了一个名为 doSomething() 的方法。在上下文中,MyService 类被用作目标对象,即需要被拦截和增强的对象。

public class MyService {

    public String doSomething() {
        System.out.println("Doing something...");
        return "hello world";
    }
}

运行结果,成功地执行了代理对象的doSomething()方法,并在方法执行完成后,后置返回通知MyAfterReturningAdvice被触发。

Doing something...
After method doSomething is called, returned value: hello world

七、常见问题

  1. 无法拦截异常

    • 仅在目标方法成功返回时被调用,无法捕获和处理方法抛出的异常。
  2. 无法修改返回值

    • afterReturning方法可以看到方法的返回值但无法修改它。如果需要修改返回值可以考虑使用环绕通知Around Advice
  3. 无法访问方法体内的局部变量

    • 只能获取到方法的返回值、方法名称、参数和目标对象,无法访问方法内的局部变量。
  4. 无法控制方法执行流程

    • 只能在方法成功返回后执行,无法控制方法执行的前后顺序,也无法阻止方法的执行。