根本原因在於<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