Spring Aop失效的情況及解决办法

文章目录

    • 第一种(要增强的类或方法没被spring管理)
    • 第二种(要被增强的类或方法同时被spring和springMVC扫描)
    • 第三种(要增强的方法被同类的方法调用)
    • 第四种(用的注解方式没有开启注解支持)
    • 总结

第一种(要增强的类或方法没被spring管理)

对于传统的web项目来说,通常使用spring和springmvc,因此对于这种项目来讲,他是有两个容器的,一个是spring容器,一般我们会把Service层的东西注入到spring容器中,另一个是springmvc的容器,通常这个容器里注入的是Controller层的东西,这里我们认为spring容器是父容器,springmvc是子容器的概念,然后我们大家都知道通过父子继承关系可知,子容器是可以读取到父容器中的东西,但是父容器是无法读到子容器中的内容,因此基于这个场景,有的同学,把Aop的实现类注入到了spring容器中,并且将Aop的切点表达式配置 也配到了spring容器的xml,而巧了这位同学要切的类方法,正好是Controller,也就是springmvc容器中的东西,那么这时候问题就来了,aop在初始化时会在自己的容器中寻找能够匹配的类方法,然后给他套上一层代理,此时他在自己能够访问到的spring容器中根本找不到与之匹配的类和方法,因为这些类和方法是在springmvc容器中管理的,因此就没有代理成功
解决那么对于上述问题要怎么修改呢?只需要确保你要Aop切的类和方法与你Aop配置切点aop:config 表达式声明是在同一个容器中即可,此时只需要将这个配置移到springmvc容器的xml中即可

第二种(要被增强的类或方法同时被spring和springMVC扫描)

第二种情况与第一种情况有些许的类似,但并不相同,是关于重复扫描的,比如你在spring容器中配置了一个Aop,并且把他托管给spring容器管理,而且execution表达式切的也是spring容器中管理的类和方法,理论上这个时候是好用的,这批execution切到的类都被加了代理,但是巧了,springmvc容器中由于配置的是包路径扫描,恰好把execution表达式切的这一批对象又扫了一遍,又都托管给了springmvc容器,而此时扫到的这批对象,是重新new出来交给springmvc管理的,因此并没有被aop代理,所以在使用时,注入进来的可能是springmvc容器管理的这批对象,因此使用时发现Aop代理失效了
解决:这个问题的解决方案,就是避免两个容器重复扫描。

第三种(要增强的方法被同类的方法调用)

第三个问题就比较简单了,他的现象是有些方法被Aop代理成功了,但有个别方法没有代理成功,究其原因发现这部分没有代理成功的方法并不是通过代理对象调用的,而是自身调用的,故被调用的方法没有被Aop代理,无法织入横切逻辑。
解决:举个栗子,比如A.a(),A.b()是被代理的类和方法,那么当我调用A.a()时,此时a被代理了,成功执行代理类的内容,但还没有完,a()方法中调用了自身的方法b(),此时我们以为b也会被代理类代理,但实际上并没有,因为他是自身方法调用了并不是通过代理类A调用的,在a方法中可以通过((A) AopContext.currentProxy()).b()调用,不过前提是配置上expose-proxy="true"是重点

第四种(用的注解方式没有开启注解支持)

这种就更好理解了,只需要开启注解支持就行了。
xml方式开启在spring配置文件添加上即可
注解方式开启在启动类上添加@EnableAspectJAutoProxy即可

总结

第一种和第二种是因为MVC分层没有用好,接收数据和业务逻辑要分开,
第三种是因为代理模式限制
第四种就是使用不当了

参考: https://blog.csdn.net/sun5769675/article/details/95187532

你可能感兴趣的:(spring)