记一次spring切面不生效问题

这个主要是spring父子容器的问题,最近做了个项目。利用切面记录日志,需要拦截controller中的方法,但是切面一直不生效,之前一直把目光集中在是否表达式写错,或者少了配置。结果是父子容器问题。记一次spring切面不生效问题

上面是web.xml,servlet指向加载的xm就是加载再子容器中,这个子容器要加载的xml里面内容如下:

记一次spring切面不生效问题看到只是个扫描spring组件的路径,哪些组件注解标记的类会被作为springbean加载进来。

然后spring父容器启动时如果没有指定加载配置文件的路径则本身会加载类路径下的application.xml,我这用的是默认路径,application.xml配置如下:

记一次spring切面不生效问题

这里加了个开始切面的注解,<aop:aspectj-autoproxy proxy-target-class="true"/> 这个也一样,理论上<aop:aspectj-autoproxy/>是在接口上利用jdk动态代理生成代理(切面的最终就是将用方法加上切面中的增强逻辑生成代理,外部调用的时候实际是调到代理)<aop:aspectj-autoproxy proxy-target-class="true"/>是利用cglib代理原理针对具体类型生成代理,而controller是具体类型,但是我这试过<aop:aspectj-autoproxy/> 这个也能进切面。

因为项目之前没有切面,所以还需要引入aspectjweaver的jar包,而spring-aop本身原本就有,不用再引入了。

这里发现子容器和父容器都有扫描spring组件的配置,而这个<aop:aspectj-autoproxy/>标签我是加在application.xml中的,如上图。想当然的以为父容器在扫描完spring组件后再进行切面处理,而实际上是切面进不去,没有生效。应该是子容器扫描了spring组件,父容器进行切面编织的时候找不到要编织的spring组件,这里是controller。然后纠结了n久,一直以为那里配错了,写错了,最终才把目光转移到是不是父子容器的问题,把这个标签加在子容器配置文件中如下图:

记一次spring切面不生效问题

才使得切面可用。这里父容器和子容器都扫描了spring组件,结果是子容器加载了,我这边尝试把只保留一个扫描spring组件配置,结果发现如果再父容器中扫描,那么controller不可用,外部访问404,但是组件里面打上断点发现断点是存活的(有小勾勾),

记一次spring切面不生效问题

以下没有小勾勾是死断点:

记一次spring切面不生效问题

即加容器载到了组件,这个要后续研究了。而子容器进行扫描是ok的。

总结:就是个spring父子容器的问题。类似java继承,子可以继承父的东西,能拿到父的东西,父不能拿到子的东西。