欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot搭配AOP實現(xiàn)自定義注解

 更新時間:2022年12月09日 08:16:32   作者:糖拌西紅柿  
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何搭配AOP實現(xiàn)自定義注解,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

1.springBoot的依賴

確定項目中包含可以注解的依賴

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

2.自定義注解的步驟

在項目中自定義注解的步驟主要有兩步,第一步:定義注解類,第二步:定義切面

2.1定義注解類

直接創(chuàng)建 @interface的類,使用注解@Target和 @Retention指定其適用范圍及保留時長,如下:

@Target(ElementType.METHOD) // 指定注解的適用范圍
@Retention(RetentionPolicy.RUNTIME) //指定運(yùn)行時
public @interface ApiLog {

    String desc() default "";

    boolean timeSpan() default true;


}

注解類的內(nèi)容一般很簡單,類似于Enum類一樣,里面是簡單的方法及屬性

2.2定義切面

通過@Aspect注解指定一個類,該類必須實現(xiàn)

@Component
@Aspect
@Slf4j(topic = "ApiLogNote")
public class ElasticSearchExecuteLog {

    @Around("@annotation(com.gcc.ApiLog)")
    public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        //獲取被調(diào)用方法
        Method method = signature.getMethod();
        //取出被調(diào)用方法的注解,方便后續(xù)使用注解中的屬性
        ApiLog loglinstener = method.getAnnotation(ApiLog.class);
        log.info("----------------------method[{}]start--------------------",method.getName());
        log.info("方法描述:{}",loglinstener.desc());
        log.info("參數(shù) :{}",point.getArgs());
        long startTime = System.currentTimeMillis();
        Object proceed = point.proceed();
        long endTime = System.currentTimeMillis();
        log.info("耗時:{}ss",endTime-startTime);
        log.info("----------------------method[{}] end--------------------\n",method.getName())
        return proceed;
    }
}

2.3使用注解

因為此例子使用的類型為METHOD即方法級的注解,直接在方法上使用即可:

    @ApiLog
    public JSONObject seachEsData(String indexName, SearchSourceBuilder searchSourceBuilder) {
        JSONObject resultMap = new JSONObject();
        .......
        return resultMap;
    }

3.知識點補(bǔ)充

3.1 關(guān)于Target注解補(bǔ)充

注解@Target常常配合枚舉類ElementType來指定注解的作用位置,也叫合法位置,即你定義了一個注解,這個注解是類注解還是方法注解還是XX注解等,具體作用的范圍,取決于@Target({ElementType.TYPE})中,ElementType的枚舉值,在進(jìn)行自定義枚舉時,根據(jù)自己的需求,決定定義的注解是哪類層級使用的注解,例如上面的例子中,@ApiLog這個自定義的注解就是方法級的注解

ElementType的枚舉值有

枚舉值含義
TYPE類, 接口 (包括注解類型), 或 枚舉 聲明
FIELD字段、包括枚舉常量
METHOD方法聲明
PARAMETER正式的參數(shù)聲明
CONSTRUCTOR構(gòu)造函數(shù)的聲明
LOCAL_VARIABLE局部變量的聲明
ANNOTATION_TYPE注解類型的聲明
PACKAGE包聲明

3.2 關(guān)于Retention注解補(bǔ)充

注解@Retention常常配合枚舉類RetentionPolic來指定注解的各種策略,注解的保留時間,也就是何時生效,即你定義了一個注解,這個注解是編譯時生效還是僅僅只是在代碼中標(biāo)記等等,具體作用的范圍,取決于@Retention({RetentionPolic.TYPE})中,RetentionPolic的枚舉值,在進(jìn)行自定義枚舉時,大多數(shù)都是使用RUNTIME(編譯時生效)

RetentionPolic的枚舉值

枚舉值含義
SOURCE解只在源代碼級別保留,編譯時被忽略
CLASS注解將被編譯器在類文件中記錄 , 但在運(yùn)行時不需要JVM保留。這是默認(rèn)的
RUNTIME注解將被編譯器記錄在類文件中,在運(yùn)行時保留VM,也是使用最多的(一般自定義均使用這個)

3.3 關(guān)于AOP的一些概念補(bǔ)充

這種在運(yùn)行時,動態(tài)地將代碼切入到類的指定方法、指定位置上的編程思想就是面向切面的編程

切面

切面是一個橫切關(guān)注點的模塊化,一個切面能夠包含同一個類型的不同增強(qiáng)方法,比如說事務(wù)處理和日志處理可以理解為兩個切面。切面由切入點和通知組成,它既包含了橫切邏輯的定義,也包括了切入點的定義。 Spring AOP就是負(fù)責(zé)實施切面的框架,它將切面所定義的橫切邏輯織入到切面所指定的連接點中。簡單點理解,在SpringBoot中使用了Aspect注解的類就是切面

@Component
@Aspect
public class LogAspect {
}

目標(biāo)對象

目標(biāo)對象指將要被增強(qiáng)的對象,即包含主業(yè)務(wù)邏輯的類對象?;蛘哒f是被一個或者多個切面所通知的對象。

在我們的例子中,即是使用了@ApiLog注解的地方

連接點

程序執(zhí)行過程中明確的點,如方法的調(diào)用或特定的異常被拋出。連接點由兩個信息確定:

方法(表示程序執(zhí)行點,即在哪個目標(biāo)方法)

相對點(表示方位,即目標(biāo)方法的什么位置,比如調(diào)用前,后等)

簡單來說,連接點就是被攔截到的程序執(zhí)行點,因為Spring只支持方法類型的連接點,所以在Spring中連接點就是被攔截到的方法。

切入點

切入點是對連接點進(jìn)行攔截的條件定義。切入點表達(dá)式如何和連接點匹配是AOP的核心,Spring缺省使用AspectJ切入點語法。 一般認(rèn)為,所有的方法都可以認(rèn)為是連接點,但是我們并不希望在所有的方法上都添加通知,而切入點的作用就是提供一組規(guī)則(使用 AspectJ pointcut expression language 來描述) 來匹配連接點,給滿足規(guī)則的連接點添加通知。

//此處的匹配規(guī)則是 com.remcarpediem.test.aop.service包下的所有類的所有函數(shù)。
@Pointcut("execution(* com.remcarpediem.test.aop.service..*(..))")
public void pointcut() {
}

這里切入點的概念其實就是確定對哪些目標(biāo)對象進(jìn)行切面插入功能,一開始的例子是采用注解的方式來達(dá)到切入**點的作用

 @Around("@annotation(com.gcc.ApiLog)")

通知

通知是指攔截到連接點之后要執(zhí)行的代碼,包括了“around”、“before”和“after”等不同類型的通知。Spring AOP框架以攔截器來實現(xiàn)通知模型,并維護(hù)一個以連接點為中心的攔截器鏈。

// @Before說明這是一個前置通知,log函數(shù)中是要前置執(zhí)行的代碼,JoinPoint是連接點,
@Before("pointcut()")
public void log(JoinPoint joinPoint) { 
}

???????//@After 為后置通知

//@Around 為環(huán)繞通知

織入(Weaving)

這里的織入概念是個動作,即Spring將前面的切面、連接點、切入點關(guān)聯(lián)起來并創(chuàng)建通知代理的過程??椚肟梢栽诰幾g時,類加載時和運(yùn)行時完成。在編譯時進(jìn)行織入就是靜態(tài)代理,而在運(yùn)行時進(jìn)行織入則是動態(tài)代理。

增強(qiáng)器(Advisor)

Advisor是切面的另外一種實現(xiàn),能夠?qū)⑼ㄖ愿鼮閺?fù)雜的方式織入到目標(biāo)對象中,是將通知包裝為更復(fù)雜切面的裝配器。Advisor由切入點和Advice組成。 Advisor這個概念來自于Spring對AOP的支撐,在AspectJ中是沒有等價的概念的。Advisor就像是一個小的自包含的切面,這個切面只有一個通知。切面自身通過一個Bean表示,并且必須實現(xiàn)一個默認(rèn)接口。

簡單來講,整個 aspect 可以描述為: 滿足 pointcut 規(guī)則的 joinpoint 會被添加相應(yīng)的 advice 操作。

將上方通過注解使用切面的方式改寫一下:

@Component
@Aspect
@Sl4fj
public class ElasticSearchExecuteLog {
 
  // 不使用注解,而通過基礎(chǔ)的規(guī)則配置選擇切入點,表達(dá)式是指com.gcc.controller
 // 包下的所有類的所有方法
 @Pointcut("execution(* com.gcc.controller..*(..))")
 public void aspect() {}
 
  // 通知,在符合aspect切入點的方法前插入如下代碼,并且將連接點作為參數(shù)傳遞
 @Before("aspect()")
 public void log(JoinPoint joinPoint) { //連接點作為參數(shù)傳入
   // 獲得類名,方法名,參數(shù)和參數(shù)名稱。
   Signature signature = joinPoint.getSignature();
   String className = joinPoint.getTarget().getClass().getName();
   String methodName = joinPoint.getSignature().getName();
   Object[] arguments = joinPoint.getArgs();
   MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
   String[] argumentNames = methodSignature.getParameterNames();
   StringBuilder sb = new StringBuilder(className + "." + methodName + "(");
       for (int i = 0; i< arguments.length; i++) {
                  Object argument = arguments[i];
                  sb.append(argumentNames[i] + "->");
                  sb.append(argument != null ? argument.toString() : "null ");
       }
   sb.append(")");
   log.info(sb.toString());
  }
}

3.4關(guān)于AOP中一些類及函數(shù)的使用

JoinPoint對象

JoinPoint對象封裝了SpringAop中切面方法的信息,在切面方法中添加JoinPoint參數(shù),就可以獲取到封裝了該方法信息的JoinPoint對象.

方法作用返回對象
getSignature()獲取封裝了署名信息的對象,在該對象中可以獲取到目標(biāo)方法名,所屬類的Class等信息Signature
getArgs()獲取 獲取傳入目標(biāo)方法的參數(shù)對象Object[]
getTarget()獲取被代理的對象Object

proceedingJoinPoin對象

proceedingJoinPoin對象是JoinPoint的子類,在原本JoinPoint的基礎(chǔ)上,放開了Proceeed()的使用,一般在環(huán)繞通知@Around時使用:

Object proceed() throws Throwable //執(zhí)行目標(biāo)方法
Object proceed(Object[] var1) throws Throwable //傳入的新的參數(shù)去執(zhí)行目標(biāo)方法

以上就是SpringBoot搭配AOP實現(xiàn)自定義注解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot AOP自定義注解的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java實現(xiàn)發(fā)送短信驗證碼+redis限制發(fā)送的次數(shù)功能

    Java實現(xiàn)發(fā)送短信驗證碼+redis限制發(fā)送的次數(shù)功能

    這篇文章主要介紹了Java實現(xiàn)發(fā)送短信驗證碼+redis限制發(fā)送的次數(shù),本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • CGLIB代理的使用與原理解析

    CGLIB代理的使用與原理解析

    這篇文章主要介紹了CGLIB代理的使用與原理解析,靜態(tài)代理和JDK 代理模式都要求目標(biāo)對象是實現(xiàn)一個接口,但是有時候目標(biāo)對象只是一個單獨(dú)的對象,并沒有實現(xiàn)任何的接口,這個時候可使用目標(biāo)對象子類來實現(xiàn)代理,這就是Cglib代理,需要的朋友可以參考下
    2023-09-09
  • SpringBoot解決ajax跨域問題的方法

    SpringBoot解決ajax跨域問題的方法

    這篇文章主要為大家詳細(xì)介紹了SpringBoot解決ajax跨域問題的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 在日志中記錄Java異常信息的正確姿勢分享

    在日志中記錄Java異常信息的正確姿勢分享

    這篇文章主要介紹了在日志中記錄Java異常信息的正確姿勢,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java調(diào)用.dll文件的方法

    Java調(diào)用.dll文件的方法

    因為項目的需求,要在JAVA項目中調(diào)用Windows的Dll(動態(tài)鏈接庫)文件,之前用Jni調(diào)用過C寫的Dll文件,比較麻煩,這里不多說,網(wǎng)上也有很多這方面的文檔。在網(wǎng)上找到一個開源的組件JNative,使用后感覺比較方便
    2013-04-04
  • java自動生成接口文檔完整代碼示例

    java自動生成接口文檔完整代碼示例

    在軟件開發(fā)中,編寫接口文檔是一項必要但繁瑣的任務(wù),為了簡化這一過程,可以通過使用Swagger2和Swagger-UI來自動生成接口文檔,這篇文章主要介紹了java自動生成接口文檔的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • Java編程中靜態(tài)內(nèi)部類與同步類的寫法示例

    Java編程中靜態(tài)內(nèi)部類與同步類的寫法示例

    這篇文章主要介紹了Java編程中靜態(tài)內(nèi)部類與同步類的寫法示例,用于構(gòu)建靜態(tài)對象以及實現(xiàn)線程同步等,需要的朋友可以參考下
    2015-09-09
  • SpringBoot使用?Sleuth?進(jìn)行分布式跟蹤的過程分析

    SpringBoot使用?Sleuth?進(jìn)行分布式跟蹤的過程分析

    Spring Boot Sleuth是一個分布式跟蹤解決方案,它可以幫助您在分布式系統(tǒng)中跟蹤請求并分析性能問題,Spring Boot Sleuth是Spring Cloud的一部分,它提供了分布式跟蹤的功能,本文將介紹如何在Spring Boot應(yīng)用程序中使用Sleuth進(jìn)行分布式跟蹤,感興趣的朋友一起看看吧
    2023-10-10
  • java基礎(chǔ)篇之Date類型最常用的時間計算(相當(dāng)全面)

    java基礎(chǔ)篇之Date類型最常用的時間計算(相當(dāng)全面)

    這篇文章主要給大家介紹了關(guān)于java基礎(chǔ)篇之Date類型最常用的時間計算的相關(guān)資料,Java中的Date類是用來表示日期和時間的類,它提供了一些常用的方法來處理日期和時間的操作,需要的朋友可以參考下
    2023-12-12
  • Java操作mongodb增刪改查的基本操作實戰(zhàn)指南

    Java操作mongodb增刪改查的基本操作實戰(zhàn)指南

    MongoDB是一個基于分布式文件存儲的數(shù)據(jù)庫,由c++語言編寫,旨在為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲解決方案,下面這篇文章主要給大家介紹了關(guān)于Java操作mongodb增刪改查的基本操作實戰(zhàn)指南,需要的朋友可以參考下
    2023-05-05

最新評論