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.