学习AOP时的一个问题

这几天在公司看项目代码,翻到了aop的部分,本着学习的想法看了下使用AspectJ实现对日志的管理。但是在看这段代码的时候有一个问题一直困扰着我,就是代码的执行顺序。

困扰

@Around这个注解的作用之类的就不在这里介绍了,只说其中的一个问题,使用ProceedingJoinPoint类获得切入点之后,用proceed()方法执行被切部分的代码。

问题就在这里,公司的代码中这个Advice方法具有一个Object的返回值,是proceed()方法调用后的返回值,那么如果在被切的类中,调用了被切方法的返回值,因为赋值操作和切面操作都是在方法之后执行,那么谁会更先执行呢?

在验证之前先说个推论吧。如果赋值语句先执行那么aop方法中的返回值将毫无意义,那么方法就可以改为void的返回值类型。如果around是在编译时将目标方法包裹住,是对目标方法的一种编译时内容扩充,那么对于aop方法,就应该记录proceed方法的返回值并返回。由于around增强具有修改参数这个功能,我比较倾向于第二种,能够获得返回值甚至进行修改的看法。

说到底,能有这种困扰还是因为当初没有好好学习aop的内容,加上没有实际项目和具体问题来深入研究。现在书也还了,图书馆也关门了,只能依靠互联网了。

学习

advice 通知

通知感觉可以看作是切面需要完成的工作,这里面就包括了之前有所了解的五种通知类型。其他四种,before,after,after-returning,after-throwing都不会关心你的返回值。

pointcut 切点

切点定义的是执行通知的连接点,因为一个通知可能不需要通知所有的连接点,相当于定位操作。

join point 连接点

连接点通俗一点的说法就是能够执行通知的时间点。

其他术语不介绍了,慢慢看

根据介绍,确实是通过包裹住目标方法的方式,实现织入。那么就可以开始写代码证明了。


验证

首先找一个返回值不为void的方法,这里我用的是自己之前一个项目中查找用户实体的service。

Customer find(String id);

这个方法返回的是自己定义的一个Customer类型的对象,创建一个aop的切面来包围这个方法。

@Pointcut("execution(* com.px.service.*Service.find(..))")
private void aspectjMethod(){}

@Around(value = "aspectjMethod()")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable{
    logger.info("before method");
    Object returnValue = pjp.proceed();
    logger.info("after method");
    logger.info("returnClass: --->" + returnValue.getClass().toString());
    Customer customer = (Customer) returnValue;
    logger.info(customer.toString());
    customer.setName("Armourr");
    return customer;
    }

在这个方法中实现对目标方法的包围,执行目标方法后调用返回值returnValue.getClass().toString()得到返回对象的具体类名,然后将这个对象强制转换成Customer类型,打印相关信息并修改这个对象的部分信息,将修改后的对象作为返回值返回。

之后编写测试用例,执行service中的方法,打印返回值的相关内容信息。

@Test
public void aopTest(){
    String id = "1026";
    Customer customer = customerService.find(id);
    logger.info("return value: ----->" + customer.toString());
    }

最终控制台输出的log信息为如下,

[INFO] before method
...
...
[INFO] after method
[INFO] returnClass: --->class com.px.entity.Customer
[INFO] Customer{id='1026', name='customer25', gender='female', phone='134856225', email='customer25@163.com', description='hello world!'}
[INFO] return value: ----->Customer{id='1026', name='Armourr', gender='female', phone='134856225', email='customer25@163.com', description='hello world!'}

通过观察日志信息不难发现,find方法执行后获得的返回值是已经被aop方法修改过的。因此,可以得出程序执行到切点时,会按照aop中的代码执行相关的aop操作,之后才会返回程序原来的部分继续执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值