Spring AOP 註解形式

AspectOriented Programing,面向切面編程。

  AOP主要用於日誌記錄,性能統計,安全控制(權限控制),事務處理,異常處理等。將日誌記錄,性能統計,安全控制,事務處理,異常處理等代碼從業務邏輯代碼中劃分出來,經過對這些行爲的分離,咱們但願能夠將它們獨立到非指導業務邏輯的方法中,進而改變這些行爲的時候不影響業務邏輯的代碼。
  Spring AOP織入加強(Advice)的方式有兩種 若是鏈接點實現了接口採用jdk自帶的動態代理的形式實現織入,若是鏈接點沒有實現接口則採用動態字節碼生成技術(CGLIB)實現織入。git

AOP經常使用術語:

鏈接點(Joinpoint)

  加強程序執行的某個特定位置(要在哪一個地方作加強操做)。Spring僅支持方法的鏈接點,既僅能在方法調用前,方法調用後,方法拋出異常時等這些程序執行點進行織入加強。github

切點(Pointcut)

  切點是一組鏈接點的集合。AOP經過「切點」定位特定的鏈接點。經過數據庫查詢的概念來理解切點和鏈接點的關係再適合不過了:鏈接點至關於數據庫中的記錄,而切點至關於查詢條件。正則表達式

加強(Advice)

  加強是織入到目標類鏈接點上的一段程序代碼。表示要在鏈接點上作的操做。spring

切面(Aspect)

  切面由切點和加強(引介)組成(能夠包含多個切點和多個加強),它既包括了橫切邏輯的定義,也包括了鏈接點的定義,SpringAOP就是負責實施切面的框架,它將切面所定義的橫切邏輯織入到切面所指定的連接點中。數據庫

註解切面類例子:

@Aspect
public class LogAspect {
    @Pointcut("execution(* com.ctj.service.*.*(..))")
    public void pointcutName(){}

    @Before("pointcutName()")
    public void performance(){
        System.out.println("Spring AOP");
    }
}

 

經常使用註解:

  • @aspect 定義切面
  • @pointcut 定義切點
  • @before 標註Before Advice定義所在的方法
  • @afterreturning 標註After Returning Advice定義所在的方法
  • @afterthrowing 標註After Throwing Advice定義所在的方法
  • @after 標註 After(Finally) Advice定義所在的方法
  • @around 標註Around Advice定義所在的方法

咱們如何在定義切點(Pointcut)的時候指定一類Joinpoint呢?有兩種方式 簡單的方法名指定以及正則表達式兩種方式。編程

經常使用的@AspectJ形式Pointcut表達式的標誌符:

execution:

  Spring AOP僅支持方法執行類型的Joinpoint 因此execution將會是咱們用的最多的標誌符,用它來幫咱們匹配擁有指定方法前面的Joinpoint。匹配規則以下:
execution(modifiers-pattern? return-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern)安全

  • modifiers-pattern 修飾符 好比public private這種(能夠指定能夠不指定)
  • return-type-pattern 返回值類型(必須指定)
  • declaring-type-pattern 類型(能夠是含包名的全路徑類型 能夠指定能夠不指定)
  • name-pattern 方法名(必須指定)
  • param-pattern 參數類型(必須指定)

方法的返回類型 方法名及參數部分的匹配模式是必須指定的 其餘部分能夠省略。
咱們還能夠在表達式中使用兩種通配符:*和..
  第一:*能夠用於任何部分的匹配模式中,匹配相鄰的多個字符,即一個Work 。若是放在了方法參數的位置標示參數是任何類型的。
例如:execution(* *(String))
  第二:..通配符能夠在兩個位置使用 一個是declaring-type-pattern的位置,一個是在方法參數匹配模式的位置。
若是是放在了方法類型的位置,能夠指定多個層次的類型聲明。例如:
execution(void cn.spring.*.doSomething(*)) 指定到cn.spring下的全部類型。
若是是放在了方法參數的匹配位置,則表示該方法能夠有0到多個參數。例如:
execution(void *.doSomething(..))框架

within:

  within標誌符只接受類型聲明,它將匹配指定類型下全部的Joinpoint。
例如:within(cn.spring.aop.target.*) 將會匹配 cn.spring.aop.target包下全部類型的方法級別的Joinpoint。性能

@annotation

  使用@annotation標誌符會檢查系統中全部對象的全部方法級別Joinpoint,若是被檢測的方法標註有@annotation標誌符所指定的註解類型,那麼當前方法所在的Joinpoint將被Pointcut表達式匹配。例如:@pointcut("@annotation(com.test.aop.log.ALog)") 匹配全部使用了ALog註解的方法。spa

匹配表達式的維度有不少 上面只是一小部分經常使用的,而且這些維度是能夠組合的 使用||或者$$等等
例如:@around("within(com.test.finance..*) && @annotation(com.test.finance.platform.intf.base.db.ReadOnly)")

在定義Advice的時候 咱們匹配的維度能夠直接寫定義有@pointcut的方法名稱 也能夠直接使用定義@joinpoint的那一套東西來直接定義要在哪些地方織入(能夠直接在Advice上指定匹配哪些方法)

定義完切面以後咱們要在spring中註冊這個切面類,爲了讓spring能自動幫咱們實現織入 咱們還須要開啓自動注入 在spring配置文件中:<aop:aspectj-autoproxy proxy-target-class="true"/> 這樣spring就能在IOC容器找到全部要織入的方法 動態幫咱們織入。

一個完整的Spring AOP的小例子:

業務類代碼:

package com.ctj.service;
import org.springframework.stereotype.Service;

@Service
public class BusinessService {

    public void say(){
        System.out.println("Business Code");
    }
}

 

切面類定義:

package com.ctj.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class LogAspect {
    @Pointcut("execution(* com.ctj.service.*.*(..))")
    public void pointcutName(){}
    @Before("pointcutName()")
    public void performance(){
        System.out.println("Spring AOP");
    }
}

 

spring-aop.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    <bean id="logAspect" class="com.ctj.aspect.LogAspect">
    </bean>
</beans>

 

基於註解的Spring AOP須要JDK1.5版本之後才能使用,以前的版本須要使用基於Schema也就是配置文件的形式來實現,若是jdk版本高的話 建議仍是使用註解的形式。

相關文章
相關標籤/搜索