B类标注了@aspect及@Component,其中的b方法使用@Around拦截了A类的a方法,同时A类的a方法添加了@Transactional注解。当C类的c方法调用A类的a方法后,B类的b方法并不会拦截到a方法的执行,这种情况的原因是啥?如何解决
C类的c方法调用A类的a方法,你这C类中的A类,是注入进去的吗?最好把相关代码复制上来看看。
对,A类是一个service类,在C类中是通过@resource注解注入的,并且C类也是添加了@service注解的一个service类
没有代码,很难猜。
第一个和第二个图是C类中注入了A类并且调用了A类的a方法,第三个图是B类
我感觉像是你的Aop没有开启成功。你仔细看看DEBUG日志。还有就是你是从哪里看出来所谓的“B类的b方法并不会拦截到a方法的执行”。
第二个截图中的代码执行后(也是就C类调用完A类的a方法),B类的@around方法没有执行,根据这个判断出来没生效的
我怀疑你的Aop配置没有生效,你添加了注解@EnableAspectJAutoProxy
注解没有?
执行A类的其他方法是可以正常被拦截到的,springboot项目默认是开启的吧
兄弟,还有啥思路吗
就这些信息的话,我没啥思路。如果可以的话,你把项目发布到Github上,我可以clone下来帮忙看看。
好,我写个例子到时候@你
你好,有github访问不了 我传到码云上了 麻烦协助看一下,demo例子 中访问test1 调用save方法不会被拦截,访问test2 调用update方法可以正常被拦截
我看了一下,把save
方法放到XXXServiceImpl
就可以被切到。至于为什么父类实现方法不能被代理我也不清楚现在。
我在网上也查看了一些资料,好像普遍都有这个说法:
execution() 匹配父类的某个方法, 那么aop对其子类的这个方法都有效, 即使子类重写了父类的方法扔有效
execution() 匹配子类的某个方法, 如果这个方法是继承自父类的, 那么只有当子类重写了父类的这个方法, aop才对这个方法有效; 否则无效(即使execution不是通过通配符, 而是明确指定子类某个继承方法, 也是无效的)
可以考虑使用 within
表达式,这种表达式可以代理指定接口其子类的实现的所有方法。
@Around("within(cn.com.test.IService+)")
public Object aopTest(ProceedingJoinPoint p) throws Throwable {
System.out.println(p.getSignature().getName() + ": 执行前");
Object ret = p.proceed();
System.out.println(p.getSignature().getName() + ": 执行后");
return ret;
}
执行日志
save: 执行前
execute save
save: 执行后
upate: 执行前
around .XXXService.upate
execute update
upate: 执行后
特地留意了下这个问题。我也拉代码看了一下。在 AopUtils.canApply 的方法中看出 会选择出一个最佳实现方式作为连接点。而 最佳连接点是serviceImpl.save ,从此连接点中查找候选匹配,是无法找到XXXService.save的,因为serviceImpl.save和XXXService.save就没有任何关系,它是实现的IService.save。所以就无法和切点相匹配。如果你的serviceImpl.save 是 实现的XXXService.save 则能够找到切点。同理,你around换成Iservice也可以。