想使用AOP Annotation配置Spring MVC的Controller進行攔截, 發現沒法攔截Controller的方法, 卻能夠攔截Service層的方法.web
一開始:spring
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層的自動掃描配置.json
代碼2:spring-mvc.xml <context:component-scan base-package="com.hodc.sdk.controller" />
加強代碼爲以下:spring-mvc
代碼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; }
須要被攔截的方法以下:mvc
代碼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寫法也沒有做用.app
參照http://stackoverflow.com/questions/17834958/spring-aop-is-not-working-in-with-mvc-structure?rq=1oop
由於Spring的Bean掃描和Spring-MVC的Bean掃描是分開的, 二者的Bean位於兩個不一樣的Application, 並且Spring-MVC的Bean掃描要早於Spring的Bean掃描, 因此當Controller Bean生成完成後, 再執行Spring的Bean掃描,Spring會發現要被AOP代理的Controller Bean已經在容器中存在, 配置AOP就無效了.spa
一樣這樣的狀況也存在於數據庫事務中, 若是Service的Bean掃描配置在spring-mvc.xml中, 而數據庫事務管理器配置在application.xml中, 會致使數據庫事務失效, 原理同樣.代理
因此這裏 ,咱們須要把AOP放置在Controller掃描配置的文件中.
Spring的配置文件application.xml包含了 開啓AOP自動代理,Service掃描配置, 如今只包含了service的自動掃描配置
代碼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都是有效的,可是第一種是最精確的.