1. 程式人生 > >Spring與SpringBoot:SpringAOP使用@Aspect

Spring與SpringBoot:SpringAOP使用@Aspect

      在spring中,AOP和IOC都是spring非常重要的特性,而在web開發中,定義切面、增強方法也是比較常見的,比如做統一的日誌管理相關的、自定義的註解處理、或者在處理使用者請求的前後我們需要做一些處理,等等,這時我們都可以使用切面來實現,而在以前,使用切面我們可能需要使用很多介面和類,現在,我們只需要@Aspect這一個註解就可以定義切面。

      首先,我們定義一個類,然後在這個類上使用@Aspect註解,這樣一個切面就定義好了,我們可以再加上@Component註解,這樣就把這個切面交給Spring容器來管理。

@Aspect
@Component
public class RecommendLogAspect {
}

       接下來就是定義切點,並對切點做一些增強操作:前置增強、環繞增強、後置增強等等,切點的定義我們可以在一個空方法體的方法上使用@Pointcut註解

@Pointcut("@annotation(com.sino.baseline.common.annotation.InitQueryParam)")
	public void pointcut() {}

@Pointcut()裡面定義的是切點表示式,切點表示式有很多,上面例子程式碼中的是註解表示式,標註來指定註解的目標類或者方法,就比如凡是使用了com.sino.baseline.common.annotation.InitQueryParam這個註解的類或者方法都是切點。除了@annotation()還有幾類比較常見的切點表示式:

        1.execution(方法修飾符 返回型別 方法全限定名 引數)

          匹配指定的方法,例如

@Pointcut("execution(* com.tcb.controller.SDProductController.showproductDetail(..))")
         *  匹配任意字元,但只能匹配一個元素
         ..  匹配任意字元,可以匹配任意多個元素,表示類時,必須和*聯合使用

         +  必須跟在類名後面,如Student+,表示類本身和繼承或擴充套件指定類的所有類

        2. args( 引數型別的類全限定名 )

         匹配引數是指定型別的方法,比如@Pointcut(com.xx.Student) 就是匹配所有引數是student類物件的方法,像void add(Student s)這樣的方法就會被匹配。

        3. @args( 註解類的類全限定名 )

           匹配引數的型別的類被指定註解修飾的方法,注意,這個引數的型別還必須是自定義的類,比如@Pointcut(com.xx.anno.ExAnno),你有一個一個方法void(Student s){},而引數型別Student是你自定義的類,而Student這個類被@ExAnno修飾了,那麼,這個方法就會被匹配(這個地方有點坑!)。

        4. within( 類全限定名 )

            匹配指定的類,比如@Pointcut(com.xx.IndexController)就是IndexController類下的方法都會被匹配,這裡的類名支援正則模糊匹配,比如@Pointcut(com.xx.*Controller)就是com.xx包下的所有的Controller都會被匹配。對了,上面和下面的表示式都支援正則模糊匹配。

        5. target( 類全限定名 )

            匹配指定的類以及它的子類,比如@Pointcut(com.xxx.dao.BaseDao)就是匹配BaseDao介面以及所有實現類這個介面的子類。

        6. @within( 類全限定名 )

            匹配使用了指定的註解的類以及它的子類,比如@Pointcut(com.xxx.anno.Log)就是指,我在BaseController裡使用了@Log註解,那麼BaseController以及繼承BaseController的類都會被匹配。

        7. @target( 類全限定名 )

              匹配使用了指定註解的類(從這裡我們看出來,within、target和@within、@target是相反,鬱悶。。。),還是@Pointcut(com.xxx.anno.Log)就是僅匹配使用了@Log註解的類

    ok,以上是一些較常用的切點表示式,然後繼續之前的。

    在定義切點之後,我們就可以對切點進行增強操作(注意,我前面@Pointcut註解修飾的方法名是pointcut()哦),比如@Before("pointcut()")前置增強,@Around("pointcut()")環繞增強。。。等等,注意,我這裡直接使用的前面定義切點的那個方法名,這種方式屬於獨立切點命名(劃重點!),就是將切點單獨定義出來,對於當切點較多時,能夠提高一些重用性。這種算是顯式地定義切點,除了這種還可以使用匿名切點,即直接在增強操作方法裡直接寫切點表示式,比如:

@Before("execution(* com.tcb.controller.SDProductController.showproductDetail(..))")
	public void beforeBrowse(JoinPoint joinPoint) {}

      好了,增強主要有以下幾種:

        1. @Before

            前置增強,在切點方法執行之前執行。這裡多說幾句,在增強方法中要獲取request可以通過下面來獲取:

ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();

在前置增強中,想要獲取切點方法的引數可以通過joinPoint.getArgs[]來獲取,獲取方法名可以通過joinPoint.getSignature().getDeclaringTypeName()來獲取。

         2. @Around

            環繞增強

        3. @AfterReturning

            後置增強,切點方法正常執行完返回後執行,如果有異常丟擲而退出,則不會執行增強方法

        4. @AfterThrowing

            後置增強,只有切點方法異常丟擲而退出後執行

        4. @After

            也是後置增強,但不管切點方法是正常退出還是異常退出都會執行

    好了,以上就是AOP開發基於@Aspect等註解的使用方法,有新的心得再隨時修改或者寫第二篇,有不對的地方歡迎指摘,吃飯嘍大笑