springBoot使用註解整合Aop實例介紹

Aop:面向切面編程,即是橫向重複、縱向抽取思想。

springAop:底層封裝了動態代理和cglib代理的代碼,我們不需要手寫動態代理的代碼,封裝的兩個代理可以對任何類進行增強。

使用Aop的注意事項/坑:
1)、不宜把重要業務放在Aop中處理。
2)、Aop不處理Static、final、private方法
3)、無法攔截內部方法調用

spring名詞:
1)連接點(JoinCut):目標對象中所有可以增強的方法,可以認爲是類中的所欲方法

2)切入點(PointCut):目標對象中需要對它進行增強的方法

3)切面(Aspect):切入點+通知

4)織入(Weaving):將通知織入到切入點的過程叫做織入

5)目標對象(Target):即是需要增強的類

6)代理(Proxy):將通知織入到目標對象之後生成代理對象

7)通知/增強(Advice):對切入點所增強的代碼

 

通知類型:

前置通知:(在調用目標對象之前執行)

環繞通知:(在目標對象調用之前和調用之後都會執行)

異常通知:(在調用目標對象之後執行)

後置通知(出現異常也會執行):(在調用目標對象之後異常情況下也會執行)

後置通知(出現異常不會執行):(在調用目標對象之後異常情況下不會執行)

 

springBoot整合Aop實例介紹

1、導入依賴 

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2、設置方法接口

package com.ltj.demo.Service.Interface;


/**
 * 接口測試類
 */
public interface interfaceA {

    //增加
    public String save(int args1,int args2);

}

3、實現接口

package com.ltj.demo.Service;

import com.ltj.demo.Service.Interface.interfaceA;
import org.springframework.stereotype.Service;


/**
 * 設置通知
 */

@Service
public class interfaceAImpl implements interfaceA {

    @Override
    public String save(int mathScore,int engScore) {
        System.out.println("保存成功");
        System.out.println("the total score is : " + mathScore+engScore);
        return "保存成功22";
    }

}

4、設置通知類

package com.ltj.demo.Service;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 通知/增強名詞
 *      前置通知(在調用目標對象之前執行)
 *      後置通知(異常情況下不會執行)
 *      環繞通知(在目標對象調用之前和調用之後都會執行)
 *      異常通知(在調用目標對象之後執行)
 *      後置通知(異常情況下也會執行)
 */

/**
 * @Aspect:該註解設置該類爲切面
 * @Component
 */
@Aspect
@Component
public class MyAdvice {

    //設置方法作爲切入點
    @Pointcut(value = "execution(* com.ltj.demo.Service.interfaceAImpl.*(..))")
    public void pointCut(){}

    //設置前置通知
    @Before("MyAdvice.pointCut()")
    public void before(JoinPoint joinPoint){
        Object[] obj = joinPoint.getArgs();             //獲取連接點方法運行時的入參列表
        String methodName = joinPoint.getSignature().getName();
        Object paramter1 = joinPoint.getSignature().getDeclaringType();
        Object paramter2 = joinPoint.getSignature().getDeclaringTypeName();
        Object paramter3 = joinPoint.getSignature().getModifiers();

        System.out.println(methodName);                     //獲取目標對象的方法名
        System.out.println(paramter1);
        System.out.println(paramter2);
        System.out.println(paramter3);

        System.out.println(joinPoint.getThis());                                    //獲取代理對象本身
        System.out.println(joinPoint.getTarget());                                  //獲取連接點所在的目標對象

        for (Object objs: obj) {                //循環獲取入參值
            System.out.println("入參:" + objs);
        }
        System.out.println("我是前置通知");
    }

    /**
     * 設置後置通知(異常情況下也會執行)
     * @param joinPoint 目標類連接點對象
     */
    @After("MyAdvice.pointCut()")
    public void after(JoinPoint joinPoint){
        System.out.println("設置後置通知(異常情況下也會執行)");
    }

    //設置後置通知(異常情況下不會執行)
    @AfterReturning(value="MyAdvice.pointCut()", returning ="results")      //value設置切入點,results爲返回值
    public void afterReturn(JoinPoint joinPoint,Object results){            //results設置參數接收返回值

        System.out.println("設置後置通知(異常情況下不會執行)");

        System.out.println("返回值爲:" + results);          //輸出results返回值,即是目標對象的返回值
    }

    /**
     * 設置異常通知
     * @param proceedingJoinPoint   JoinPoint的子接口
     */
    @AfterThrowing("MyAdvice.pointCut()")
    public void afterThrow(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("我是異常通知");
    }

    /**
     * 設置環繞通知
     * @param proceedingJoinPoint   JoinPoint的子接口
     */
    @Around("MyAdvice.pointCut()")
    public void around(ProceedingJoinPoint proceedingJoinPoint){
        String methodName = proceedingJoinPoint.getSignature().getName();
        Object result = null;
        try {
            System.out.println("我是環繞通知");
            result = proceedingJoinPoint.proceed();                 //通過反射執行目標對象的連接點處的方法
            System.out.println("環繞通知的名稱爲:" + methodName +
                    ",返回的執行結果是:" + result);
        }catch (Throwable throwable){
            throwable.printStackTrace();
            System.out.println("異常返回");
        }
    }
}

5、使用測試類進行測試

package com.ltj.demo.Service;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import static org.junit.Assert.*;

@SpringBootTest
@RunWith(SpringRunner.class)
public class interfaceAImplTest {

    //自動注入
    @Autowired
    interfaceAImpl interfaceAImp;

    @Test
    public void example() {
        //調用保存方法
        interfaceAImp.save(1,2);
    }

}

友情鏈接:

AspectJ JoinPoint及ProceedingJoinPoint 簡要api文檔:https://blog.csdn.net/airjordon/article/details/83623830

SpringBoot集成ApringAOP:https://www.cnblogs.com/zdj-/p/8665454.html

springAop視同註解實現5種通知類型:https://www.cnblogs.com/fengxiangyu/p/10896547.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章