Java自定义注解详解
文章目录
- 一、注解基础
- 注解的作用
- Java内置注解
- 二、元注解
- @Retention
- @Target
- @Documented
- @Inherited
- @Repeatable(Java 8)
- 三、创建自定义注解
- 基本语法
- 注解属性
- 使用自定义注解
- 四、注解的处理方式
- 1. 编译时处理
- 2. 运行时处理(反射)
- 五、实际应用场景
- 1. 依赖注入框架
- 2. 单元测试框架
- 3. 参数验证
- 4. JSON序列化/反序列化
- 5. 日志记录与性能监控
- 6. 权限控制
- 六、自定义注解结合反射的完整示例
- 1. 定义注解
- 2. 实现验证器
- 3. 使用示例
- 七、自定义重复注解(Java 8+)
- 1. 定义重复注解
- 2. 使用重复注解
- 3. 处理重复注解
- 八、自定义注解最佳实践
- 九、总结
一、注解基础
注解(Annotation)是Java 5引入的特性,它提供了一种为程序元素(类、方法、变量等)添加元数据的方式。注解本身不会影响程序的执行,但可以被编译器、运行时环境或其他工具读取并处理。
注解的作用
- 提供编译器信息 - 帮助编译器检测错误或抑制警告
- 编译时和部署时处理 - 生成代码、XML文件等
- 运行时处理 - 通过反射读取注解信息,实现特定功能
Java内置注解
Java提供了几个内置注解,如:
- @Override - 标记方法覆盖父类方法
- @Deprecated - 标记已过时的元素
- @SuppressWarnings - 抑制编译器警告
- @FunctionalInterface - 标记函数式接口
- @SafeVarargs - 抑制与可变参数相关的警告
二、元注解
元注解是用于注解其他注解的注解。Java提供了几个重要的元注解:
@Retention
定义注解的保留策略:
public enum RetentionPolicy {SOURCE, // 仅在源代码中保留,编译时丢弃CLASS, // 保留在编译后的类文件中,但JVM运行时不保留(默认行为)RUNTIME // 保留至运行时,可通过反射API访问
}
@Target
指定注解可应用的程序元素类型:
public enum ElementType {TYPE, // 类、接口、枚举FIELD, // 字段、枚举常量METHOD, // 方法PARAMETER, // 方法参数CONSTRUCTOR, // 构造函数LOCAL_VARIABLE, // 局部变量ANNOTATION_TYPE, // 注解类型PACKAGE, // 包TYPE_PARAMETER, // 类型参数(Java 8)TYPE_USE, // 类型使用(Java 8)MODULE // 模块(Java 9)
}
@Documented
指示注解应该被包含在JavaDoc中。
@Inherited
指示注解可以被子类继承。
@Repeatable(Java 8)
指示注解可以在同一元素上多次使用。
三、创建自定义注解
基本语法
自定义注解的语法与接口定义类似,使用@interface关键字:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {// 注解属性声明
}
注解属性
注解可以包含属性(也称为元素):
public @interface MyAnnotation {String value(); // 无默认值的属性String name() default ""; // 带默认值的属性int age() default 0;String[] roles() default {};
}
注解属性的类型限制:
- 基本类型(int, float, boolean等)
- String
- Class
- 枚举类型
- 注解类型
- 以上类型的数组
使用自定义注解
@MyAnnotation(value = "测试", name = "张三", age = 25, roles = {"admin", "user"})
public void someMethod() {// 方法实现
}// 当只有value属性需要设置时,可以简写
@MyAnnotation("测试")
public void anotherMethod() {// 方法实现
}
四、注解的处理方式
1. 编译时处理
使用注解处理器(Annotation Processor)在编译时处理注解。这通常用于代码生成、编译时验证等。
示例:创建一个简单的编译时注解处理器
// 定义注解
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Builder {
}// 创建注解处理器
@SupportedAnnotationTypes("com.example.Builder")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class BuilderProcessor extends AbstractProcessor {@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {// 处理逻辑return true;}
}
2. 运行时处理(反射)
使用Java反射API在运行时读取和处理注解。
示例:运行时处理注解
// 定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {boolean enabled() default true;
}// 使用注解
public class MyTest {@Test(enabled = true)public void testMethod1() {// 测试代码}@Test(enabled = false)public void testMethod2() {// 测试代码}
}// 处理注解
<