根本原因在于<aop:aspectj-autoproxy />这句话是在spring的配置文件内,还是在springmvc的配置文件内。如果是在spring的配置文件内,则@Controller中的方法不会被拦截。
看一下applicationContext.xml中bean扫描的配置,此处排除了controller层的扫描:
<context:component-scan base-package="com"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <context:component-scan base-package="icom"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan>
看一下springmvc-servlet.xml中bean扫描的配置,此处排除了service层的扫描:
<context:component-scan base-package="com"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan> <context:component-scan base-package="icom"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan>
所以要拦截哪层的类中的方法,就应该在相应的配置文件中添加<aop:aspectj-autoproxy />
解决办法:
注释掉applicationContext.xml中的<aop:aspectj-autoproxy />,在springmvc-servlet.xml中配置:
<bean id="aspectBean" class="icom.axx.action.AopAspect" /> <aop:aspectj-autoproxy />
另外,不要忘记增加:
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation=
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
除非整个web应用中只配置一个<component-scan>,且这个base-package同时包含了所有要扫描的包时,才会出现Controller的bean的初始化早于其它bean的情况。
如果是Spring的Bean扫描文件和spring-mvc-servlet中的的bean扫描文件是分开的,那么就是先扫描Spring的Bean;最后才扫描spring-mvc的bean。因为Spring的Bean是由监听器ContextLoaderListener负责扫描装载的,而spring-mvc的servlet-config.xml中配置的<component-scan>bean处于Servlet级别的,监听器的启动顺序自然要早于Servlet的启动顺序。
出现AOP切不到Controller的真正原因在于<aop:aspectj-autoproxy/>这句的位置。
更具体的原因:假如你在两份配置文件:spring-config.xml springmv-servlet.xml中都配置了扫描全部的包,那么你会发现所有的Bean都被先后实例化了一次,先spring-config.xml ;后 springmv-servlet.xml。两者实例化的Bean分别放在了父子容器中。
第一次初始化AController时,是在spring-config.xml 中(里面有aspectj-autoproxy配置),这时,这个AControllerBean就会被初始化为AOP代理对象,存在父容器中。
然后 springmv-servlet.xml中并没有aspectj-autoproxy,所以AControllerBean就是一个普通Bean,存在子容器中,没有被AOP代理。
当URL访问Controller时,就会用到子容器中的普通ControllerBean,所以AOP切不到。
所以在项目开发中,最好是明确职责边界,Spring-application-config.xml只负责核心的Bean初始化;springmvc-servlet-config.xml只负责和mvc相关的bean:比如Controller、HandlerMapping、HandlerAdapter.
参考:
https://www.cnblogs.com/Frank-Hao/p/5787813.html
作者:架构师小跟班
开发者导航: http://www.codernav.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果文中有什么错误,欢迎指出,以免更多的人被误导。