技术来自于需求 组内在做性能测试,要知道每个方法调用时候,外层方法以及内部调用的每个子方法的耗时时长,第一时间呢就想到了在方法前后打印时间,然后做差值打印 但是里面的调用链比较长,然后写了好多好多差值打印代码...
基于上述情况呢,我就想着做个annotation给方法去使用,想打印方法执行时间的方法呢就把我的annotation加上去就行了 先说下额外的一个小选型废弃
同一类里调用别的AOP方法,写下伪代码,类似下面代码
@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 目标对象 直接调用,并不是代理对象进行调用
通过代理对象调用~
final TestController proxy = (TestController) AopContext.currentProxy();
proxy.time2();
//构造器注入其他bean
private final CacheManager cacheManager;
//annotation注入其他bean
@Autowired
private Temp temp;
@Service
public class SomeService {
//注入自己
@Autowired
private SomeService self
}
另在查阅资料时候发现有人的aop失效是因为没开启cglib,这里也提一下啊,想要使用aop,要做以下配置