詳解SpringBoot如何自定義注解
1.什么是注解
注解(Annotation),也叫元數(shù)據(jù)。一種代碼級(jí)別的說(shuō)明。它是JDK1.5及以后版本引入的一個(gè)特性,與類、接口、枚舉是在同一個(gè)層次。它可以聲明在包、類、字段、方法、局部變量、方法參數(shù)等的前面,用來(lái)對(duì)這些元素進(jìn)行說(shuō)明,注釋。
元注解
有一些注解可以修飾其他注解,這些注解就稱為元注解(meta annotation)。Java標(biāo)準(zhǔn)庫(kù)已經(jīng)定義了一些元注解,我們只需要使用元注解,通常不需要自己去編寫(xiě)元注解。
@Target
最常用的元注解是@Target。使用@Target可以定義Annotation能夠被應(yīng)用于源碼的哪些位置:
- 類或接口:
ElementType.TYPE; - 字段:
ElementType.FIELD; - 方法:
ElementType.METHOD; - 構(gòu)造方法:
ElementType.CONSTRUCTOR; - 方法參數(shù):
ElementType.PARAMETER。
例如,定義注解@Report可用在方法上,我們必須添加一個(gè)@Target(ElementType.METHOD):
@Target(ElementType.METHOD)
public @interface Report {
int type() default 0;
String level() default "info";
String value() default "";
}
定義注解@Report可用在方法或字段上,可以把@Target注解參數(shù)變?yōu)閿?shù)組{ ElementType.METHOD, ElementType.FIELD }:
@Target({
ElementType.METHOD,
ElementType.FIELD
})
public @interface Report {
...
}
實(shí)際上@Target定義的value是ElementType[]數(shù)組,只有一個(gè)元素時(shí),可以省略數(shù)組的寫(xiě)法。
@Retention
另一個(gè)重要的元注解@Retention定義了Annotation的生命周期:
- 僅編譯期:
RetentionPolicy.SOURCE; - 僅class文件:
RetentionPolicy.CLASS; - 運(yùn)行期:
RetentionPolicy.RUNTIME。
如果@Retention不存在,則該Annotation默認(rèn)為CLASS。因?yàn)橥ǔN覀冏远x的Annotation都是RUNTIME,所以,務(wù)必要加上@Retention(RetentionPolicy.RUNTIME)這個(gè)元注解:
@Retention(RetentionPolicy.RUNTIME)
public @interface Report {
int type() default 0;
String level() default "info";
String value() default "";
}
@Repeatable
使用@Repeatable這個(gè)元注解可以定義Annotation是否可重復(fù)。這個(gè)注解應(yīng)用不是特別廣泛。
@Repeatable(Reports.class)
@Target(ElementType.TYPE)
public @interface Report {
int type() default 0;
String level() default "info";
String value() default "";
}
@Target(ElementType.TYPE)
public @interface Reports {
Report[] value();
}
經(jīng)過(guò)@Repeatable修飾后,在某個(gè)類型聲明處,就可以添加多個(gè)@Report注解:
@Report(type=1, level="debug")
@Report(type=2, level="warning")
public class Hello {
}
@Inherited
使用@Inherited定義子類是否可繼承父類定義的Annotation。@Inherited僅針對(duì)@Target(ElementType.TYPE)類型的annotation有效,并且僅針對(duì)class的繼承,對(duì)interface的繼承無(wú)效:
@Inherited
@Target(ElementType.TYPE)
public @interface Report {
int type() default 0;
String level() default "info";
String value() default "";
}
在使用的時(shí)候,如果一個(gè)類用到了@Report:
@Report(type=1)
public class Person {
}
則它的子類默認(rèn)也定義了該注解:
public class Student extends Person {
}
2.代碼工程
實(shí)驗(yàn)?zāi)康?/h3>
實(shí)現(xiàn)統(tǒng)計(jì)方法執(zhí)行時(shí)間的注解
實(shí)現(xiàn)統(tǒng)計(jì)方法執(zhí)行時(shí)間的注解
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springboot-demo</artifactId>
<groupId>com.et</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>annotations</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.21</version>
</dependency>
</dependencies>
</project>
controller
使用自定義注解@RequestTime
package com.et.annotation.controller;
import com.et.annotation.RequestTime;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class HelloWorldController {
@RequestMapping("/hello")
@RequestTime
public Map<String, Object> showHelloWorld(){
Map<String, Object> map = new HashMap<>();
map.put("msg", "HelloWorld");
return map;
}
}
custom annotation
自定義@RequestTime注解
package com.et.annotation;
import java.lang.annotation.*;
/**
* computa the excute time for the method
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface RequestTime {
}
具體的攔截邏輯類
package com.et.annotation;
import com.et.annotation.util.AspectUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Slf4j
@Aspect
@Component
public class RequestTimeAspect {
@Pointcut(value = "@annotation(com.et.annotation.RequestTime)")
public void pointcut() {
}
@Around("pointcut()")
public Object handle(ProceedingJoinPoint point) throws Throwable {
Method currentMethod = AspectUtil.getMethod(point);
long starttime = System.currentTimeMillis();
Object result = point.proceed();
long endtime = System.currentTimeMillis();
long requesttime =endtime-starttime;
//if(requesttime>1000){
log.info(AspectUtil.getClassName(point)+"."+currentMethod.getName()+"execute time:"+requesttime+" ms");
//}
return result;
}
}
以上只是一些關(guān)鍵代碼,所有代碼請(qǐng)參見(jiàn)下面代碼倉(cāng)庫(kù)
代碼倉(cāng)庫(kù)
- https://github.com/Harries/springboot-demo(annotations)
3.測(cè)試
啟動(dòng)Spring Boot應(yīng)用程序
訪問(wèn)http://127.0.0.1:8088/hello
控制臺(tái)輸出 日志
2024-08-10 19:30:43.670 INFO 3343 --- [nio-8088-exec-1] com.et.annotation.RequestTimeAspect : com_et_annotation_controller_HelloWorldController.showHelloWorldexecute time:41 ms
以上就是詳解SpringBoot如何自定義注解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot自定義注解的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot實(shí)現(xiàn)自定義注解用于文件驗(yàn)證的詳細(xì)過(guò)程(大小、擴(kuò)展名、MIME類型)
- SpringBoot自定義注解解決公共字段填充問(wèn)題解決
- Springboot使用redisson?+?自定義注解實(shí)現(xiàn)消息的發(fā)布訂閱(解決方案)
- SpringBoot3使用?自定義注解+Jackson實(shí)現(xiàn)接口數(shù)據(jù)脫敏的步驟
- SpringBoot+Redisson自定義注解一次解決重復(fù)提交問(wèn)題
- Springboot自定義注解&傳參&簡(jiǎn)單應(yīng)用方式
相關(guān)文章
Spring強(qiáng)大事務(wù)兼容數(shù)據(jù)庫(kù)多種組合解決業(yè)務(wù)需求
這篇文章主要為大家介紹了Spring強(qiáng)大事務(wù)兼容數(shù)據(jù)庫(kù)多種組合解決業(yè)務(wù)需求示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
java實(shí)現(xiàn)導(dǎo)出Excel的功能
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)導(dǎo)出Excel的功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
Spring?boot?Jpa添加對(duì)象字段使用數(shù)據(jù)庫(kù)默認(rèn)值操作
這篇文章主要介紹了Spring?boot?Jpa添加對(duì)象字段使用數(shù)據(jù)庫(kù)默認(rèn)值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
java實(shí)現(xiàn)簡(jiǎn)單學(xué)生管理系統(tǒng)項(xiàng)目
這篇文章主要介紹了java實(shí)現(xiàn)簡(jiǎn)單學(xué)生管理系統(tǒng)項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
Java獲取中文拼音、中文首字母縮寫(xiě)和中文首字母的示例
本文主要介紹了Java獲取中文拼音、中文首字母縮寫(xiě)和中文首字母,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-10-10
java sql ResultSet 之getRow()用法說(shuō)明
這篇文章主要介紹了java sql ResultSet 之getRow()用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
使用Spring的ApplicationEvent實(shí)現(xiàn)本地事件驅(qū)動(dòng)的實(shí)現(xiàn)方法
本文介紹了如何使用Spring的ApplicationEvent實(shí)現(xiàn)本地事件驅(qū)動(dòng),通過(guò)自定義事件和監(jiān)聽(tīng)器,實(shí)現(xiàn)模塊之間的松耦合,提升代碼的可維護(hù)性和擴(kuò)展性。同時(shí)還介紹了異步事件和事件傳遞的相關(guān)知識(shí)2023-04-04
Java啟動(dòng)時(shí)循環(huán)依賴處理方式
解決Spring Boot啟動(dòng)時(shí)由于SwaggerAutoConfiguration注解重復(fù)啟用導(dǎo)致的循環(huán)導(dǎo)入問(wèn)題,通過(guò)排除SwaggerAutoConfiguration并手動(dòng)開(kāi)啟Swagger配置2026-01-01
Java語(yǔ)言實(shí)現(xiàn)基數(shù)排序代碼分享
這篇文章主要介紹了Java語(yǔ)言實(shí)現(xiàn)基數(shù)排序代碼分享,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12

