自定义注解全面详解

目录

  • 一、注解概述
    • [1.1 什么是注解](#1.1 什么是注解)
    • [1.2 注解的作用](#1.2 注解的作用)
  • 二、注解基础
    • [2.1 内置注解](#2.1 内置注解)
    • [2.2 元注解(用于定义注解的注解)](#2.2 元注解(用于定义注解的注解))
  • 三、自定义注解定义
    • [3.1 基本语法](#3.1 基本语法)
    • [3.2 注解元素类型限制](#3.2 注解元素类型限制)
  • 四、元注解详解
    • [4.1 @Target - 指定使用位置](#4.1 @Target - 指定使用位置)
    • [4.2 @Retention - 指定保留策略](#4.2 @Retention - 指定保留策略)
    • [4.3 例子](#4.3 例子)
  • 五、注解使用示例
    • [5.1 字段验证注解](#5.1 字段验证注解)
    • [5.2 API接口注解](#5.2 API接口注解)
  • 六、注解处理器
    • [6.1 编译时处理(APT)](#6.1 编译时处理(APT))
    • [6.2 运行时处理(反射)](#6.2 运行时处理(反射))
  • 七、高级特性
    • [7.1 重复注解(Java 8+)](#7.1 重复注解(Java 8+))
    • [7.2 类型注解(Java 8+)](#7.2 类型注解(Java 8+))

一、注解概述

1.1 什么是注解

注解(Annotation)是Java 5引入的一种元数据机制,用于为代码添加额外的信息,这些信息可以被编译器、运行时环境或其他工具读取和处理。

1.2 注解的作用

编译器检查(如@Override

代码生成(如Lombok

运行时处理(如Spring注解)

文档生成(如@Deprecated

二、注解基础

2.1 内置注解

clike 复制代码
@Override    // 检查方法是否重写父类方法
@Deprecated  // 标记已过时
@SuppressWarnings  // 抑制编译器警告
@FunctionalInterface  // 函数式接口

2.2 元注解(用于定义注解的注解)

java 复制代码
@Target       // 指定注解可以应用的位置
@Retention    // 指定注解的保留策略
@Documented   // 是否包含在Javadoc中
@Inherited    // 是否允许子类继承
@Repeatable   // 是否可重复使用(Java 8+)

三、自定义注解定义

3.1 基本语法

java 复制代码
// 定义注解
public @interface MyAnnotation {
    // 注解元素(属性)
    String value() default "default";
    int count() default 0;
    String[] tags() default {};
}

// 使用注解
@MyAnnotation(value = "test", count = 5, tags = {"a", "b"})
public class MyClass {
    @MyAnnotation
    public void method() {}
}

其中的属性值都是有括号的value()

3.2 注解元素类型限制

注解元素只能是以下类型:

基本类型(int、boolean等)

String

Class

enum

Annotation

以上类型的数组

四、元注解详解

4.1 @Target - 指定使用位置

java 复制代码
@Target(ElementType.TYPE)           // 类、接口、枚举
@Target(ElementType.FIELD)          // 字段
@Target(ElementType.METHOD)         // 方法
@Target(ElementType.PARAMETER)      // 参数
@Target(ElementType.CONSTRUCTOR)    // 构造器
@Target(ElementType.LOCAL_VARIABLE) // 局部变量
@Target(ElementType.ANNOTATION_TYPE)// 注解
@Target(ElementType.PACKAGE)        // 包
@Target(ElementType.TYPE_PARAMETER) // 类型参数(Java 8+)
@Target(ElementType.TYPE_USE)       // 类型使用(Java 8+)

// 允许多个位置
@Target({ElementType.TYPE, ElementType.METHOD})

4.2 @Retention - 指定保留策略

java 复制代码
@Retention(RetentionPolicy.SOURCE)   // 仅源码,编译后丢弃
@Retention(RetentionPolicy.CLASS)    // 编译到class文件,运行时不可见
@Retention(RetentionPolicy.RUNTIME)  // 运行时可见,可通过反射读取

4.3 例子

java 复制代码
import java.lang.annotation.*;

// 定义一个运行时注解,可用于类和方法
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface CustomAnnotation {
    String name() default "";
    String description();
    int version() default 1;
    Status status() default Status.ACTIVE;
    
    // 嵌套注解
    Author[] authors() default {};
    
    // 枚举
    enum Status {
        ACTIVE, INACTIVE, DEPRECATED
    }
    
    // 注解中的注解
    @interface Author {
        String name();
        String email() default "";
    }
}

五、注解使用示例

5.1 字段验证注解

java 复制代码
// 定义验证注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Validation {
    boolean required() default false;
    int minLength() default 0;
    int maxLength() default Integer.MAX_VALUE;
    String regex() default "";
    String message() default "验证失败";
}

// 使用注解
public class User {
    @Validation(required = true, minLength = 2, maxLength = 20, 
                message = "用户名长度2-20字符")
    private String username;
    
    @Validation(required = true, regex = "^(?=.*[A-Za-z])(?=.*\\d).{6,}$",
                message = "密码必须包含字母和数字,至少6位")
    private String password;
    
    @Validation(regex = "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$",
                message = "邮箱格式不正确")
    private String email;
}

5.2 API接口注解

java 复制代码
// 定义REST API注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiEndpoint {
    String path();
    HttpMethod method() default HttpMethod.GET;
    String description() default "";
    boolean requireAuth() default false;
    String[] roles() default {};
    
    enum HttpMethod {
        GET, POST, PUT, DELETE, PATCH
    }
}

// 使用注解
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @ApiEndpoint(
        path = "/{id}",
        method = ApiEndpoint.HttpMethod.GET,
        description = "根据ID获取用户",
        requireAuth = true,
        roles = {"ADMIN", "USER"}
    )
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.getUser(id);
    }
}

六、注解处理器

6.1 编译时处理(APT)

java 复制代码
// 定义注解处理器
@SupportedAnnotationTypes("com.example.Validation")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class ValidationProcessor extends AbstractProcessor {
    
    @Override
    public boolean process(Set<? extends TypeElement> annotations, 
                          RoundEnvironment roundEnv) {
        for (TypeElement annotation : annotations) {
            Set<? extends Element> elements = 
                roundEnv.getElementsAnnotatedWith(annotation);
            
            for (Element element : elements) {
                // 处理注解,生成代码等
                Validation validation = element.getAnnotation(Validation.class);
                // 生成验证代码
            }
        }
        return true;
    }
}

6.2 运行时处理(反射)

java 复制代码
// 注解处理器工具类
public class AnnotationProcessor {
    
    public static void processValidation(Object obj) throws IllegalAccessException {
        Class<?> clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        
        for (Field field : fields) {
            if (field.isAnnotationPresent(Validation.class)) {
                field.setAccessible(true);
                Validation validation = field.getAnnotation(Validation.class);
                Object value = field.get(obj);
                
                // 执行验证逻辑
                validateField(field.getName(), value, validation);
            }
        }
    }
    
    private static void validateField(String fieldName, Object value, 
                                     Validation validation) {
        if (validation.required() && value == null) {
            throw new ValidationException(fieldName + "不能为空");
        }
        
        if (value instanceof String) {
            String strValue = (String) value;
            if (strValue.length() < validation.minLength()) {
                throw new ValidationException(validation.message());
            }
            if (strValue.length() > validation.maxLength()) {
                throw new ValidationException(validation.message());
            }
            if (!validation.regex().isEmpty()) {
                if (!strValue.matches(validation.regex())) {
                    throw new ValidationException(validation.message());
                }
            }
        }
    }
}

七、高级特性

7.1 重复注解(Java 8+)

java 复制代码
// 1. 定义容器注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Roles {
    Role[] value();
}

// 2. 定义可重复注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Roles.class)
public @interface Role {
    String value();
}

// 3. 使用
@Role("ADMIN")
@Role("USER")
public class User {
    // 等价于 @Roles({@Role("ADMIN"), @Role("USER")})
}

7.2 类型注解(Java 8+)

java 复制代码
// 定义类型注解
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NonNull {
}

// 使用
public class TypeAnnotationExample {
    private @NonNull String name;  // 字段类型
    
    public List<@NonNull String> filter(
        @NonNull List<String> list) {  // 参数和泛型类型
        return list.stream()
            .filter(s -> s != null)
            .collect(Collectors.toList());
    }
}
相关推荐
爱上妖精的尾巴2 小时前
5-39 WPS JS宏 综合实例应用-4(多条件筛选记录并排序)
java·后端·restful·wps·js宏·jsa
柯南二号2 小时前
【后端】【Java】可直接落地的 Nginx + Java(Spring Boot)+ Redis 的短链系统实现
java·spring boot·nginx
廋到被风吹走2 小时前
【Spring】对多线程的支持
java·后端·spring
pyniu2 小时前
redis day1
java·前端·spring
dzl843942 小时前
2025年技术栈备忘
java
心动啊1212 小时前
简单学下chromaDB
开发语言·数据库·python
江上鹤.1482 小时前
Day33类装饰器
开发语言·python
二川bro2 小时前
性能分析指南:Python cProfile优化实战
开发语言·python
lynnlovemin2 小时前
从暴力到高效:C++ 算法优化实战 —— 排序与双指针篇
java·c++·算法