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

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

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

1.springBoot的依賴

確定項(xiàng)目中包含可以注解的依賴

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

2.自定義注解的步驟

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

2.1定義注解類

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

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

    String desc() default "";

    boolean timeSpan() default true;


}

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

2.2定義切面

通過(guò)@Aspect注解指定一個(gè)類,該類必須實(shí)現(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("耗時(shí):{}ss",endTime-startTime);
        log.info("----------------------method[{}] end--------------------\n",method.getName())
        return proceed;
    }
}

2.3使用注解

因?yàn)榇死邮褂玫念愋蜑镸ETHOD即方法級(jí)的注解,直接在方法上使用即可:

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

3.知識(shí)點(diǎn)補(bǔ)充

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

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

ElementType的枚舉值有

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

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

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

RetentionPolic的枚舉值

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

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

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

切面

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

@Component
@Aspect
public class LogAspect {
}

目標(biāo)對(duì)象

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

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

連接點(diǎn)

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

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

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

簡(jiǎn)單來(lái)說(shuō),連接點(diǎn)就是被攔截到的程序執(zhí)行點(diǎn),因?yàn)镾pring只支持方法類型的連接點(diǎn),所以在Spring中連接點(diǎn)就是被攔截到的方法。

切入點(diǎn)

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

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

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

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

通知

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

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

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

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

織入(Weaving)

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

增強(qiáng)器(Advisor)

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

簡(jiǎn)單來(lái)講,整個(gè) aspect 可以描述為: 滿足 pointcut 規(guī)則的 joinpoint 會(huì)被添加相應(yīng)的 advice 操作。

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

@Component
@Aspect
@Sl4fj
public class ElasticSearchExecuteLog {
 
  // 不使用注解,而通過(guò)基礎(chǔ)的規(guī)則配置選擇切入點(diǎn),表達(dá)式是指com.gcc.controller
 // 包下的所有類的所有方法
 @Pointcut("execution(* com.gcc.controller..*(..))")
 public void aspect() {}
 
  // 通知,在符合aspect切入點(diǎn)的方法前插入如下代碼,并且將連接點(diǎn)作為參數(shù)傳遞
 @Before("aspect()")
 public void log(JoinPoint joinPoint) { //連接點(diǎn)作為參數(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對(duì)象

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

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

proceedingJoinPoin對(duì)象

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

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

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

相關(guān)文章

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

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

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

    CGLIB代理的使用與原理解析

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

    SpringBoot解決ajax跨域問(wèn)題的方法

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

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

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

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

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

    java自動(dòng)生成接口文檔完整代碼示例

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

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

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

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

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

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

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

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

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

最新評(píng)論