🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
Spring AOP是基于代理的。 在编写自己的切面或使用Spring Framework提供的任何基于Spring AOP的切面之前,理解代理的本质是非常重要的。 考虑第一种场景,很普通的,没有被代理的对象: ~~~java public class SimplePojo implements Pojo { public void foo() { // 通过this直接调用对象方法 this.bar(); } public void bar() { //业务逻辑 } } ~~~ 直接调用对象的方法,如下所示: ![直接调用对象方法](https://box.kancloud.cn/a5b9820f6966a822e41d142e3e7f6d13_468x190.png) ~~~java public class Main { public static void main(String[] args) { Pojo pojo = new SimplePojo(); // 直接调用pojo对象的方法 pojo.foo(); } } ~~~ 如果是代理对象调用,会有一些变化,如下: ![代理对象调用](https://box.kancloud.cn/5a57c069072c576c4cdd6792f9723230_508x192.png) ~~~java public class Main { public static void main(String[] args) { ProxyFactory factory = new ProxyFactory(new SimplePojo()); factory.addInterface(Pojo.class); factory.addAdvice(new RetryAdvice()); Pojo pojo = (Pojo) factory.getProxy(); // 代理对象的方法调用 pojo.foo(); } } ~~~ 在`Main`类的`main`方法中引用了代理对象.代理对象方法的调用会委托所有的拦截器(建议的接入点)执行. 但是,如果直接引用的目标对象自身调用,则不会被代理,如`this.bar()`是目标对象的执行,而不是代理对象. 最好重构代码,不要发生自调用.或者在逻辑内使用spring aop,最好别这么用,耦合太严重 ~~~java public class SimplePojo implements Pojo { public void foo() { // 调用的是代理对象方法,但是这种写法耦合严重 ((Pojo) AopContext.currentProxy()).bar(); } public void bar() { // some logic... } } ~~~ 而且在获取代理对象时,需要额外的配置 ~~~java public class Main { public static void main(String[] args) { ProxyFactory factory = new ProxyFactory(new SimplePojo()); factory.adddInterface(Pojo.class); factory.addAdvice(new RetryAdvice()); factory.setExposeProxy(true); Pojo pojo = (Pojo) factory.getProxy(); // this is a method call on the proxy! pojo.foo(); } } ~~~ 最后,记住,spring aop代理不支持自调用的问题.