自定義注解是 Java 高級(jí)特性,核心分為 3 步:定義注解 → 給注解加元注解 → 解析注解(讓注解生效)。
核心概念
注解本質(zhì):一個(gè)帶 @interface 的接口
元注解:給自定義注解加規(guī)則的注解(必須加)
@Target:注解能用在哪里(類、方法、字段等)
@Retention:注解保留到什么時(shí)候(源碼 / 編譯 / 運(yùn)行時(shí))
解析注解:通過(guò)反射讀取注解信息,讓注解真正生效
須掌握的 4 個(gè)元注解

image.png
實(shí)際業(yè)務(wù)場(chǎng)景
權(quán)限校驗(yàn):@RequiresAdmin
日志記錄:@LogOperation
參數(shù)校驗(yàn):@NotNull、@Length
接口限流:@RateLimit
自定義緩存:@MyCache
完整實(shí)現(xiàn)一(解釋注解)
- 定義自定義注解
import java.lang.annotation.*;
// 元注解:指定注解作用范圍(方法、字段、類)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
// 元注解:指定注解保留到運(yùn)行時(shí)(必須寫,否則反射讀不到)
@Retention(RetentionPolicy.RUNTIME)
// 自定義注解
public @interface MyAnnotation {
// 定義注解屬性(默認(rèn)值可選)
String value() default "默認(rèn)值";
int age() default 18;
boolean isCheck() default true;
}
- 使用自定義注解
// 作用在類上
@MyAnnotation(value = "測(cè)試類", age = 20)
public class TestClass {
// 作用在字段上
@MyAnnotation(value = "用戶名字段", isCheck = false)
private String username;
// 作用在方法上
@MyAnnotation("登錄方法") // 只有value屬性可省略名稱
public void login() {
System.out.println("執(zhí)行登錄方法");
}
}
- 解析注解(核心:反射實(shí)現(xiàn))
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class AnnotationParser {
public static void main(String[] args) throws Exception {
// 1. 獲取目標(biāo)類的Class對(duì)象
Class<TestClass> clazz = TestClass.class;
// ====================== 解析類上的注解 ======================
if (clazz.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation classAnno = clazz.getAnnotation(MyAnnotation.class);
System.out.println("類注解信息:");
System.out.println("value = " + classAnno.value());
System.out.println("age = " + classAnno.age());
}
// ====================== 解析字段上的注解 ======================
Field field = clazz.getDeclaredField("username");
if (field.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation fieldAnno = field.getAnnotation(MyAnnotation.class);
System.out.println("\n字段注解信息:");
System.out.println("value = " + fieldAnno.value());
System.out.println("isCheck = " + fieldAnno.isCheck());
}
// ====================== 解析方法上的注解 ======================
Method method = clazz.getDeclaredMethod("login");
if (method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation methodAnno = method.getAnnotation(MyAnnotation.class);
System.out.println("\n方法注解信息:");
System.out.println("value = " + methodAnno.value());
}
}
}
- 運(yùn)行結(jié)果
類注解信息:
value = 測(cè)試類
age = 20
字段注解信息:
value = 用戶名字段
isCheck = false
方法注解信息:
value = 登錄方法