前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >内部方法的annotation没被拦截, AOP失效了...分析

内部方法的annotation没被拦截, AOP失效了...分析

作者头像
名字是乱打的
发布2021-12-24 08:59:53
1K0
发布2021-12-24 08:59:53
举报
文章被收录于专栏:软件工程

技术来自于需求 组内在做性能测试,要知道每个方法调用时候,外层方法以及内部调用的每个子方法的耗时时长,第一时间呢就想到了在方法前后打印时间,然后做差值打印 但是里面的调用链比较长,然后写了好多好多差值打印代码...

基于上述情况呢,我就想着做个annotation给方法去使用,想打印方法执行时间的方法呢就把我的annotation加上去就行了 先说下额外的一个小选型废弃

  • 摒弃threadlocal记录时间,本来想直接用threadlocal记录,然后在全局返回体内拦截的适合去除时间即可,但是由于我们方法内许多方法都是可以异步进行提高性能的,用到了多线程,所以这个方案就废弃了
  • 最终方案呢 是用annotation增强我们的方法,将方法执行时间打印到mdc里,然后在全局拦截器(一个对方法返回值再封装的拦截器形如 m,d,e)里加了一个t (map结构),将我们的mdc关于时间打印的都放进去了
AOP失效了啥情况?

同一类里调用别的AOP方法,写下伪代码,类似下面代码

代码语言:javascript
复制
@PostMapping("/timeRecode")
    @TimeRecord
    public String timeRecode() throws InterruptedException {
        time1();
        TimeUnit.SECONDS.sleep(1);
        time2();
        return "ok";
    }

    @TimeRecord
    public void time1() throws InterruptedException {
        TimeUnit.SECONDS.sleep(1);
    }

    @TimeRecord
    public void time2() throws InterruptedException {
        TimeUnit.SECONDS.sleep(1);
    }

按照我的预期应该是三个方法都被拦截到的,但是实验证明只有timeRecode被拦截了,time1().time2()没被拦截,分析下,两者不同的是前者是外部方法,而后面两者是内部调用的.

原因分析:

Spring AOP采用代理的方式实现AOP,我们编写的横切逻辑被添加到动态生成的代理对象中,只要我们调用的是代理对象,则可以保证调用的是被增强的代理方法。而在代理对象中,不管你的横切逻辑是怎样的,也不管你增加了多少层的横切逻辑,有一点可以确定的是,你终归会调用目标对象的同一方法来调用原始的业务逻辑。 如果目标对象中的原始方法依赖于其他对象,那么Spring会注入所依赖对象的代理对象,从而保证依赖的对象的横切逻辑能够被正常织入。而一旦目标对象调用的是自身的其他方法时,问题就来了,这种情况下,目标对象调用的并不是代理对象的方法,故被调用的方法无法织入横切逻辑。

我们这里方法 A 被调用,是基于 AOP 生成的 代理对象 进行的调用;方法 B 调用方法 A ,是 this 目标对象 直接调用,并不是代理对象进行调用

解决方案

通过代理对象调用~

    1. 同一个类内方法互相调用可以拿到Spring给我们创建的代理,用代理调用就可以解决,解决如下:
代码语言:javascript
复制
final TestController proxy = (TestController) AopContext.currentProxy();
        proxy.time2();
    1. 采用注入的方式把要调用的bean先注入进来,再通过bean去调用,这也适用于同一个类,其实我们也可以把自己的bean注入到自己方法内使用.
代码语言:javascript
复制
//构造器注入其他bean
private final CacheManager cacheManager;
//annotation注入其他bean
@Autowired
private  Temp temp;
代码语言:javascript
复制
@Service
public class SomeService {
    //注入自己
    @Autowired
    private SomeService self
}
ps:

另在查阅资料时候发现有人的aop失效是因为没开启cglib,这里也提一下啊,想要使用aop,要做以下配置

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/8/10 下,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AOP失效了啥情况?
  • 原因分析:
  • 解决方案
  • ps:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档