Spring的Aspect切面類不能攔截Controller中的方法


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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM