1. 程式人生 > >Spring如何使用aop切入controller層---問題筆記

Spring如何使用aop切入controller層---問題筆記

一般操作方式,但是這個對controller層無效:

package com.*.windrunner.aop; 
 import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; 
 @Aspect @Component public class ControllerLogAspect { 
  
    @Before(value = "execution(* com.*.windrunner.controller.*(..))") 
    public void beforeMethod(JoinPoint point) { 
        System.out.println("------test aop before"); 
    } 
  
}


解決方案:

1、controller裡面無法直接這樣切入的。

需要切入 execution(* org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..)) 

因為你controller註解的類,都被這個org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter給代理了。

2、

/** 
* 異常日誌處理 
 *  
 * @param joinPoint 
 * @param throwable 
 */ // 攔截語法 
// AbstractAction的子類被@RequestMapping註解的方法 
@Around("within(cn.org.sysu.cems.utils.superclass.AbstractAction+) && @annotation(org.springframework.web.bind.annotation.RequestMapping)") public ModelAndView handleError(ProceedingJoinPoint joinPoint) {

主要是那個@annotation 如果光用execution的話可能會把你Controller本身的getter setter等非請求處理方法一併給攔截了。

3、

 目測大部分同學的aop失效都是因為在springmvc的配置檔案裡面掃描了類,那麼spring去掃描的時候發現記憶體中已經有了物件,就不會在對類進行aop增強。所以當我們確定在那一層切入的時候,那麼在springmvc的配置檔案中,應該要排除欲切入的層。


<!-- 掃描的時候過濾掉Service層,aop要在service進行切入!  -->
<context:component-scan base-package="com.xxx.infoaudit"> 
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/> 
</context:component-scan>


在spring裡面掃描service 層 
<context:component-scan base-package="com.**.service" />

關於第3點,直接切入service,貌似沒什麼問題。

<aop:aspectj-autoproxy />
<bean class="com.xx.aop.LogAspect" />

<context:component-scan base-package="com.xx.dao"/>
<context:component-scan base-package="com.xx.service"/>


關於切入點所在的類,這些類必須使用Spring context初始化,否則AOP將不會被執行。  

Indeed your controller (annotated by @Controller) and your aspects (annotated by @Aspect) should be in the same Spring context.

Usually people define their controllers in the dispatch-servlet.xml or xxx-servlet.xml and their service beans (including the aspects) in the main applicationContext.xml. It will not work.

When Spring initializes the MVC context, it will create a proxy for your controller but if your aspects are not in the same context, Spring will not create interceptors for them.