SSM學習—Spring(第六天學習記錄)

Aop

  • AOP(Aspect-Oriented Programming,面向切面編程):是一種新的方法論,是對傳統OOP(Object-Oriented Programming,面向對象編程)的補充。
  • AOP編程操作的主要對象是切面(aspect),而切面模塊化橫切關注點(可以把切面當做一個有特殊功能的類)
  • 在應用AOP編程時,仍然需要定義公共功能,但可以明確的定義這個功能應用在哪裏,以什麼方式應用,並且不必修改受影響的類。這樣一來橫切關注點就被模塊化到特殊的類裏——這樣的類我們通常稱之爲“切面”
    在這裏插入圖片描述

專業名詞

  1. 橫切關注點
    從每個方法中抽取出來的同一類非核心業務。(例如上圖的日誌)
  2. 切面(Aspect)
    封裝橫切關注點信息的類,每個關注點體現爲一個通知方法。
  3. 通知(Advice)
    切面必須要完成的各個具體工作
  4. 目標(Target)
    被通知的對象
  5. 代理(Proxy)
    向目標對象應用通知之後創建的代理對象
  6. 連接點(Joinpoint)
    橫切關注點在程序代碼中的具體體現,對應程序執行的某個特定位置。例如:類某個方法調用前、調用後、方法捕獲到異常後等。
    在應用程序中可以使用橫縱兩個座標來定位一個具體的連接點:

在這裏插入圖片描述
7. 切入點(pointcut):
定位連接點的方式。每個類的方法中都包含多個連接點,所以連接點是類中客觀存在的事物。如果把連接點看作數據庫中的記錄,那麼切入點就是查詢條件——AOP可以通過切入點定位到特定的連接點。切點通過org.springframework.aop.Pointcut 接口進行描述,它使用類和方法作爲連接點的查詢條件。

在這裏插入圖片描述

細節

切入點表達式:通過表達式去定位一個或多個具體的連接
	語法格式:execution([權限修飾符] [返回值類型] [簡單類名/全類名] [方法名]([參數列表]))

在這裏插入圖片描述

當前連接點所在方法的方法名、當前傳入的參數值等等。這些信息都封裝在JoinPoint接口的實例對象中	

在這裏插入圖片描述

	@Component      //先標示爲組件,交給IOC容器管理
@Aspect         //標識爲切面
@Order(2)
public class LoggingAspect {
    /**
     * 前置通知:在目標方法執行之前執行的方法
     * 注意導包的時候不要導錯了
     * 切入點表達式
     * execution(public int Aspectj.Before.ArithmeticCalculatorimpl.add(int,int))
     *聲明切入點表達式
     */
    @Pointcut("execution(* Aspectj.Before.*.*(..))")
    public void declarePointCut(){

    }
   // @Before("execution(public int Aspectj.Before.ArithmeticCalculatorimpl.add(int,int))")
    @Before("declarePointCut()")
    public void beforeMethod(JoinPoint joinPoint){
        Object args[]=joinPoint.getArgs();
        System.out.println("前置通知:"+ Arrays.asList(args));
    }
    /**
     * 後置通知:在目標方法之後執行,不管目標方法有沒有拋出異常
     *	  		*    * com.atguigu.spring.aspectJ.annotation.*.*(..)
	 *  	    * : 任意修飾符 任意返回值
	 *    		* : 任意類
	 *    		* : 任意方法
	 *    		..: 任意參數列表
	 *    
     */
    @After("execution(* Aspectj.Before.*.*(..))")
    public void AfterMethod(JoinPoint joinPoint){
        //方法的名字
        String methodName=joinPoint.getSignature().getName();
        System.out.println("後置通知:"+methodName);
    }
    /**
     * 返回通知:在目標方法正常執行結束之後執行,可以獲取方法的返回值
     * 通過returning來制定一個名字,必須與方法裏的形參一樣
     */
    @AfterReturning(value="execution(* Aspectj.Before.*.*(..))",returning = "result")
    public void AfterReturnMethod(JoinPoint joinPoint,Object result){
        //方法的名字
        String methodName=joinPoint.getSignature().getName();
        System.out.println("返回通知:"+methodName+"返回結果"+result);
    }
    @AfterThrowing(value = "execution(* Aspectj.Before.*.*(..))",throwing = "ex")
    public void AfterThrowMethod(JoinPoint joinPoint,Exception ex){
        //方法的名字
        String methodName=joinPoint.getSignature().getName();
        System.out.println("異常通知:"+ex);
    }
    /**
     * 環繞通知:環繞着目標方法執行,可以理解爲前置,後置,返回,異常的結合體更像是動態代理的過程
     */
    @Around(value = "execution(* Aspectj.Before.*.*(..))")
    public Object AroundMethod(ProceedingJoinPoint joinPoint){
        //執行目標放阿飛
       try {
           //前置
           Object obj=joinPoint.proceed();

           return obj;
            //返回
       }catch (Throwable e){
           e.printStackTrace();
       }finally {
           //後置
       }
        return null;
    }
}

Aspectj(Java社區裏最完整的AOP框架)

所需jar包

com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar 
spring-aop-5.2.0.RELEASE.jar
spring-aspects-5.2.0.RELEASE.jar

命名空間

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
	

重用切入點定義

1)在編寫AspectJ切面時,可以直接在通知註解中書寫切入點表達式。但同一個切點表達式可能會在多個通知中重複出現。
2)在AspectJ切面中,可以通過@Pointcut註解將一個切入點聲明成簡單的方法。切入點的方法體通常是空的,因爲將切入點定義與應用程序邏輯混在一起是不合理的。
3)切入點方法的訪問控制符同時也控制着這個切入點的可見性。如果切入點要在多個切面中共用,最好將它們集中在一個公共的類中。在這種情況下,它們必須被聲明爲public。在引入這個切入點時,必須將類名也包括在內。如果類沒有與這個切面放在同一個包中,還必須包含包名。
4)其他通知可以通過方法名稱引入該切入點

代碼實現:
	  @Pointcut("execution(* Aspectj.Before.*.*(..))")
    public void declarePointCut(){

    }
   // @Before("execution(public int Aspectj.Before.ArithmeticCalculatorimpl.add(int,int))")
    @Before("declarePointCut()")
在不同的文件裏面調用
    //@Before("execution(* Aspectj.Before.*.*(..))")
    @Before("Aspectj.Before.LoggingAspect.declarePointCut()")

指定切面優先級

1)在同一個連接點上應用不止一個切面時,除非明確指定,否則它們的優先級是不確定的。
2)切面的優先級可以通過實現Ordered接口或利用@Order註解指定。
3)實現Ordered接口,getOrder()方法的返回值越小,優先級越高。

@Component
@Aspect
@Order(1)    //設置切面優先級,int類型的值,2147483647
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章