在使用AOP时难免会踩各种坑,当然百度上也有一些对应的解决方法,此次就我自己本人在应用AOP的时候所遇到的问题做个总结
问题描述:使用@Aspect注解声明切面后,在controller层引用@annotation时AOP不生效。
问题解决:
经过查找资料及自己验证得出:
1.是父子容器的问题
2.我的切面代码和连接点,通知都没有问题,问题出在了配置信息上面。
- 1
- 2
(部分借鉴)CGLIB代理配置在了applicationContext.xml 核心配置文件中,该配置文件会被ContextLoaderListenerclass加载,Spring会创建一个WebApplicationContext上下文,称为父上下文(父容器) ,保存在ServletContext中,key为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。
而spring-mvc.xml是DispatcherServlet,可以同时配置多个,每个 DispatcherServlet有一个自己的上下文对象(WebApplicationContext),称为子上下文(子容器),子上下文可以访问父上下文中的内容,但父上下文不能访问子上下文中的内容。 它也保存在 ServletContext中,key是”org.springframework.web.servlet.FrameworkServlet.CONTEXT”+Servlet名称
当spring加在父容器的时候就会去找切入点,但是这个时候切入的controller是在子容器中的,父容器是无法访问子容器,所以就拦截不到。如果将上述的配置文件放到spring-mvc.xml中,那么问题就解决了。我已经测试可以通过URL访问触发切点了。
解决方法:
- 1
- 2
- 3
- 4
总结:
归根结底来说,其实是bean的代理问题,涉及普通的bean,service,controller。下面的要注意。
Spring MVC 和 Spring 整合的时候,SpringMVC的spring-mvc.xml文件中配置扫描包,不要包含 service的注解,Spring的applicationContext.xml文件中配置扫描包时,不要包含controller的注解。
在此贴出spring-mvc.xml和application.xml的关键配置
①spring-mvc.xml----->
<aop:aspectj-autoproxy proxy-target-class="true"/>②application.xml------>
<context:component-scan base-package="com.jxkj.audit_center"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan>
附属:aop想要切面controller,必须在扫描controller的xml中,引入<aop:aspectj-autoproxy proxy-target-class="true"/>