Spring AOP切入接口validate方法不生效问题咨询(默认方法场景)
首先得拆解清楚Spring AOP的底层逻辑——它默认采用JDK动态代理(当目标类实现接口时)。动态代理的核心是生成一个实现目标接口的代理类,所有对目标方法的外部调用必须经过这个代理类,才能触发对应的切面逻辑。
那为什么你的validate方法拦截不到?核心原因就在这里:
当接口的默认方法
isValidObject调用同接口的validate方法时,这个调用是直接通过this(也就是接口实现类的原始对象)发起的,完全没经过Spring生成的代理对象。
而调用isValidObject时AOP能生效,是因为你是通过代理对象触发的这个方法,代理类会先执行切面逻辑,再去调用目标对象的isValidObject方法。
另外你提到的"3 Spring AOP marker at this line"提示,这只是IDE(比如IntelliJ IDEA)识别到这是合法的Spring AOP切入点表达式给出的标记,不代表切入点语法有问题,只是实际运行时因为调用链路没走代理,导致切面没触发而已。
解决思路
针对这个问题,有几个可行的方案:
通过AopContext获取代理对象调用方法
开启Spring AOP的代理暴露功能,在默认方法里通过代理对象调用validate:- 先在配置类上添加
@EnableAspectJAutoProxy(exposeProxy = true) - 修改默认方法代码:
default Boolean isValidObject(String A) { ComplexObject B = new ComplexObject(); Test proxy = (Test) AopContext.currentProxy(); SomeObject someObject = proxy.validate(A, B); return someObject.isValid(); }
这样调用
validate时就走了代理对象,切面就能正常拦截了。- 先在配置类上添加
改用AspectJ织入
Spring AOP的动态代理只能拦截代理对象的外部调用,而AspectJ是直接修改字节码的方式,可以拦截类内部的方法调用。你可以选择编译时织入(Compile-Time Weaving)或者加载时织入(Load-Time Weaving),这样不管是内部还是外部调用,都能触发切面逻辑。重构代码逻辑
如果允许调整代码结构,可以把默认方法里的逻辑移到实现类中,让实现类去调用validate方法。这样当通过代理对象调用实现类的方法时,validate的调用也会经过代理,从而触发切面。
内容的提问来源于stack exchange,提问作者prasingh

