这种问题的解决网上有很多种办法,这里介绍一个相对简单的。其他的更多的办法大家可以在网上找到一些案例。搜索关键词"AOP 自调用"即可。
获取代理对象进行调用我们需要修改一下前面的StrategyService的代码,修改成以下内容:
@Component public class StrategyService{ public PricingResponse getFactor(Map<String, String> pricingParams) { // 做一些参数校验,以及异常捕获相关的事情 // 这里不使用this.loadFactor而是使用AopContext.currentProxy()调用,目的是解决AOP代理不支持方法自调用的问题 if (AopContext.currentProxy() instanceof StrategyService) { return ((StrategyService)AopContext.currentProxy()).loadFactor(tieredPricingParams); } else { // 部分实现没有被代理过,则直接进行自调用即可 return loadFactor(tieredPricingParams); } } @Override @StrategyCache(keyName = "key0001", expireTime = 60 * 60 * 2) private PricingResponse loadFactor(Map<String, String> oricingParams) { //代码执行 } }即使用AopContext.currentProxy()获取到代理对象,然后通过代理对象调用对应的方法。
还有个地方需要注意,以上方式还需要将Aspect的expose-proxy设置成true。如果是配置文件修改:
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>如果是SpringBoot,则修改应用启动入口类的注解:
@EnableAspectJAutoProxy(exposeProxy = true) public class Application { } 总结以上,我们分析并解决了一个Spring AOP不支持方法自调用的问题。
AOP失败这个问题,其实还是很严重的,因为如果发生非预期的失效,那么直接问题就是没有执行切面方法,更严重的后果可能是诸如事务未生效、日志未打印、缓存未查询等各种问题。
所以,还是建议大家看完此文之后,统查一下自己的代码,是否存在方法自调用的情况。这种情况下,任何切面都是无法生效的!
关于作者:Hollis,一个对Coding有着独特追求的人,阿里巴巴技术专家,《程序员的三门课》联合作者,《Java工程师成神之路》系列文章作者。