一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第28天,点击查看活动详情。
使用this导致的一次aop失效问题
前文
本文为工作过程中遇到的一个由于使用this导致aop切面失效的问题。在此针对该问题记录一些简单的个人理解,内容难免有不正确之处,详细的原因还需要进行源码的探索。
问题描述
先陈述一下问题背景。首先进行了一下自定义注解,将其应用在需要的方法上。与此同时,进行了一些@aspect切面设置,针对该注解进行切面,意图在于针对所有被该注解修饰的方法,在切点处进行请求及返回的数据增强。而由于请求的调用过程中涉及到方法间的调用,发现一旦普通方法使用this调用时会出现切面失效的问题。
问题解决
首先来简单看一下问题中所涉及到的代码:
public void addLabelTotal(PublicTagDO publicTagDO){
switch (publicTagDO.getTagType()){
case "01":
applicationContext.getBean(LabelService.class).addLabelDeviceType(publicTagDO);
// this.addLabelDeviceType(publicTagDO);
break;
case "02":
applicationContext.getBean(LabelService.class).addLabelDevice(publicTagDO);
break;
default:
this.addLabel(publicTagDO);
break;
}
}
问题的关联代码如上图所示,此处不进行注解、切面等外围代码展示。如上图中的addLabelTotal未使用我们所自定义的注解进行修饰,而addLabelDeviceType方法则采用了我们的注解修饰。想要探索该问题出现的原因,先进行一下断点的查看,对比一下使用this与使用applicationContext.getBean(LabelService.class)时内容中存在的区别。
通过对比二者的调用我们可以发现,
this指向的是我们的原始对象,而applicationContext.getBean(LabelService.class)所指向的实际是cglib所代理的动态对象。而我们实际的增加aop注解,是作用在动态代理对象上,也就揭示了该问题出现的原因,指向的对象并非是我们用注解修饰的对象。
cglib是一种类的代理方式,主要是通过子类的继承实现,保留父类的所有功能,并对于代理的对象进行增强。上述的问题是一种典型的由于代理产生的问题。常用的aop、transaction、cache等等都存在出现这种问题的现象。在这些注解中,当我们需要进行被注解修饰的方法调用时,需要采用context进行调用取代this,以防止出现注解失效的问题。
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。