Spring AOP無法攔截Controller中的方法


想使用AOP Annotation配置Spring MVC的Controller進行攔截, 發現無法攔截Controller的方法, 卻可以攔截Service層的方法.

一開始:

Spring的配置文件application.xml包含了 開啟AOP自動代理,Service掃描配置,以及Aspect的自動掃描配置

代碼1:application.xml

<aop:aspectj-autoproxy/>

<context:component-scan base-package="com.example.sdk.service">
<context:component-scan base-package="com.hodc.sdk.aspect"/>

 

Spring MVC的配置文件spring-mvc.xml主要內容是Controller層的自動掃描配置.

代碼2:spring-mvc.xml

<context:component-scan base-package="com.hodc.sdk.controller" />

 

 

增強代碼為如下:

復制代碼
代碼3

全限定名:com.example.sdk.aspect.ControllerAspect

@Component
@Aspect
public class ControllerAspect {
       @Around(value = "execution(* com.hodc.sdk.controller.json.hadoop.HadoopClusterManage.*JsonWithException(..))") //1

//   @Around(value = "within(@org.springframework.stereotype.Controller *)") //2

//    @Around(value = "execution(* org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..))") //3
   public Object test(ProceedingJoinPoint joint) {


       Result result = new Result();

       System.out.println("in aspect");
       result = (Result) joint.proceed();
       return result;


}
復制代碼

 

 

需要被攔截的方法如下:

復制代碼
代碼4

全限定名:  com.example.sdk.controller.HadoopClusterManage#listVirtualHiveDBSJsonWithException

@RequestMapping(value = "listVirtualHiveDBS.do", produces = "application/json")
   public
   @ResponseBody
   Result listVirtualHiveDBSJsonWithException(@RequestParam("clusterId") int clusterId) {
       Result result = new Result();
       List<Db> dbs = syncServiceForWeb.listVirtualHiveDBS(clusterId);
       result.setData(dbs);
       return result;
   }
復制代碼

 

 

發現這樣配置並沒有用, 這個方法無法被攔截, 參照網上搜索的結果, 將@Around的PointCut改成代碼3中2,3寫法也沒有作用.

 

參照http://stackoverflow.com/questions/17834958/spring-aop-is-not-working-in-with-mvc-structure?rq=1

因為Spring的Bean掃描和Spring-MVC的Bean掃描是分開的, 兩者的Bean位於兩個不同的Application, 而且Spring-MVC的Bean掃描要早於Spring的Bean掃描, 所以當Controller Bean生成完成后, 再執行Spring的Bean掃描,Spring會發現要被AOP代理的Controller Bean已經在容器中存在, 配置AOP就無效了.

同樣這樣的情況也存在於數據庫事務中, 如果Service的Bean掃描配置在spring-mvc.xml中, 而數據庫事務管理器配置在application.xml中, 會導致數據庫事務失效, 原理一樣.

所以這里 ,我們需要把AOP放置在Controller掃描配置的文件中.

Spring的配置文件application.xml包含了 開啟AOP自動代理,Service掃描配置, 現在只包含了service的自動掃描配置

  1. 代碼5:application.xml
    
    <context:component-scan base-package="com.example.sdk.service">

     

Spring MVC的配置文件spring-mvc.xml主要內容是Controller層的自動掃描配置,添加了開啟AOP自動代理,以及Aspect的自動掃描配置

代碼6:spring-mvc.xml
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.hodc.sdk.aspect"/>
<context:component-scan base-package="com.hodc.sdk.controller" />

 


這樣配置情況下代碼3的3種pointcut都是有效的,但是第一種是最精確的.


免責聲明!

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



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