博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring AOP 的 afterReturing 为什么不能改变返回值
阅读量:6277 次
发布时间:2019-06-22

本文共 4117 字,大约阅读时间需要 13 分钟。

  hot3.png

    之前在开发过程中使用 @AfterReturning ,想要在切面方法中改变目标方法的返回值,但是却发现这样做不行。当时没有想到原因,后来猜测 @AfterReturing 标记的切面方法可能在 finnally 块中被调用所以不能改变返回值。今天经过测试发现这个猜测是错误的,在 finally 块中是可以改变返回值的,因为此时方法还没有返回。

public class FinallyAlterReturnValDemo {    public static String saySomething(){        return "say something ...";    }    public static Object invoke(){        String val;        try {            val =  saySomething();            return val;        }catch (Exception e){        }finally {            val = "changed return value";            return val;        }    }    public static void main(String[] args) {        Object invoke = invoke();        System.out.println(invoke);        // 执行结果是 changed return value    }}

    对Spring AOP 的 @AfterReturning 进行测试

public interface Say {    String saySomething();}
@Componentpublic class Target implements Say{    @Override    public String saySomething(){        return "say something ... ";    }}
import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.Pointcut;import org.springframework.context.annotation.EnableAspectJAutoProxy;import org.springframework.stereotype.Component;/** * Created by j4love on 2016/12/22. * Description : */@Component@org.aspectj.lang.annotation.Aspect@EnableAspectJAutoProxy()public class Aspect {    @Pointcut(value = "execution(* kernel.spring.AOP.bean.*.*(..))")    public void pointcut(){}    @AfterReturning(pointcut = "pointcut()",returning = "retVal")    public Object afterReturning(JoinPoint jp,Object retVal){        System.out.println("afterReturning ---- " + retVal);        return "change ... " + retVal;    }}
import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.aop.support.AopUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/** * Created by j4love on 2016/12/22. * Description : */@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath*:conf/spring/applicationContext-aop.xml")public class TargetTest {    @Autowired    private Say target;    @Test    public void saySomething() throws Exception {//        Object o = AopContext.currentProxy();        System.out.println("isJdkProxy = " + AopUtils.isJdkDynamicProxy(this.target));        System.out.println("isCglibProxy = " + AopUtils.isCglibProxy(this.target));        String s = this.target.saySomething();        System.out.println(s);    }}

AfterReturning 确实是无法改变返回值的,查看源码发现原因,下面贴出关键源码。

package org.springframework.aop.framework.adapter;import java.io.Serializable;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.springframework.aop.AfterAdvice;import org.springframework.aop.AfterReturningAdvice;import org.springframework.util.Assert;/** * Interceptor to wrap am {@link org.springframework.aop.AfterReturningAdvice}. * Used internally by the AOP framework; application developers should not need * to use this class directly. * * @author Rod Johnson */@SuppressWarnings("serial")public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {	private final AfterReturningAdvice advice;	/**	 * Create a new AfterReturningAdviceInterceptor for the given advice.	 * @param advice the AfterReturningAdvice to wrap	 */	public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {		Assert.notNull(advice, "Advice must not be null");		this.advice = advice;	}	@Override	public Object invoke(MethodInvocation mi) throws Throwable {		Object retVal = mi.proceed();		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());		return retVal;	}}

程序运行,目标方法被调用后,会调用 invoke(MethodInvocation mi) throws Throwable 方法,这里就会去调用目标方法,也就是说目标方法在这里就执行完了。retVal 就是目标方法的返回值。而 afterReturing 是在目标方法执行返回之后才去调用的,并且 aftreReturing 方法返回 void 所以,尽管我在@AfterReturing 标记的切面方法中有返回值也没什么作用。整个 invoke 方法最终返回的是目标方法的返回值 retVal 。这下把 @afterReturing 为什么没法改变返回值搞清楚了。

转载于:https://my.oschina.net/j4love/blog/810115

你可能感兴趣的文章
大数据技术核心之ETL
查看>>
轻松学PHP
查看>>
Android android.support.design包
查看>>
CheckBox:屏蔽setChecked方法对OnCheckedChangeListener的影
查看>>
java线程池
查看>>
UI面试内容
查看>>
Linux之RPM详解
查看>>
Windows Azure 常见问题及测试题
查看>>
flex DateChooser
查看>>
天天晚上打车--我对滴滴打车的想法
查看>>
由于MTU值设置不当造成的某些网站无法登录解决
查看>>
线程池
查看>>
聊聊高并发之隔离术
查看>>
JenKins 构建Github项目
查看>>
MySQL中from_unixtime与unix_timestamp差别
查看>>
LVS+KEEPALIVED实现高可用负载均衡架构
查看>>
Armadillo之行向量(row vector)
查看>>
搭建一个master对应2个slave
查看>>
Java 线程池的使用好处
查看>>
MySQL 双主 + keepalived 实现 HA
查看>>