Spring AOP 對Spring MVC的Controller切面攔截不起做用

#1 問題描述# 當使用Spring AOP對Controller層的Controller類的方法進行切面攔截,不起做用。AOP配置沒有任何問題。 #2 排查過程#web

  1. Spring AOP配置沒有任何問題;【正常】
  2. 斷點調試:Spring源碼斷點調試,在調用Controller方法時,Controller的實例被JDK進行動態代理了;【不正常】
  3. Spring默認的代理方式爲JDK動態代理;【正常】

#3 解決問題# AOP有的人說攔截不到Controller。有的人說想攔AnnotationMethodHandlerAdapter截到Controller必須得攔截org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterspring

首先AOP能夠攔截到Controller的,這個是毋容置疑的其次須攔截AnnotationMethodHandlerAdapter也不是必須的。最起碼我沒有驗證成功過這個。這個方式就不在這兒介紹說明了。express

AOP之因此有的人說攔截不到Controller,緣由是該註解的Controller已被spring容器內部代理了。咱們只要把它交給cglib代理就能夠了。Spring MVC的配置文件dispatcher-servlet.xml:mvc

<!-- 通知spring使用cglib而不是jdk的來生成代理方法 AOP能夠攔截到Controller -->
<aop:aspectj-autoproxy proxy-target-class="true" />

#4 問題總結# Spring MVC 和 Spring 整合的時候,SpringMVC的dispatcher-servlet.xml文件中配置掃描包,不要包含 service的註解,Spring的applicationContext.xml文件中配置掃描包時,不要包含controller的註解,以下所示:app

Spring MVC dispatcher-servlet.xml:url

<context:component-scan base-package="com.qding">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    </context:component-scan>

Spring MVC啓動時的配置文件,包含組件掃描、url映射以及設置freemarker參數,讓spring不掃描帶有@Service註解的類。爲何要這樣設置?由於springmvc.xml與applicationContext.xml不是同時加載,若是不進行這樣的設置,那麼,spring就會將全部帶@Service註解的類都掃描到容器中,等到加載applicationContext.xml的時候,會由於容器已經存在Service類,使得cglib將不對Service進行代理,直接致使的結果就是在applicationContext 中的事務配置不起做用,發生異常時,沒法對數據進行回滾。以上就是緣由所在。spa

一樣的在Spring的applicationContext.xml配置以下:prototype

<context:component-scan base-package="com.qding">           
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

context:component-scan/ 掃描指定的包中的類上的註解,經常使用的註解有:代理

@Controller 聲明Action組件
@Service    聲明Service組件    @Service("myMovieLister") 
@Repository 聲明Dao組件
@Component   泛指組件, 當很差歸類時. 
@RequestMapping("/menu")  請求映射
@Resource  用於注入,( j2ee提供的 ) 默認按名稱裝配,@Resource(name="beanName") 
@Autowired 用於注入,(srping提供的) 默認按類型裝配 
@Transactional( rollbackFor={Exception.class}) 事務管理
@ResponseBody
@Scope("prototype")   設定bean的做用域
相關文章
相關標籤/搜索