Java注解基础

Java注解基础

一、注解(Annotation)基础概念

注解是 Java 5 引入的代码元数据形式,通过 @interface 关键字定义。它们本身不直接影响代码逻辑,但通过反射机制可以被编译器、运行时或其他工具处理。典型应用场景包括:

  • 框架配置(如 Spring 的 @Controller
  • 代码生成(如 Lombok 的 @Data
  • 编译时检查(如 @Override

二、元注解(Meta-Annotation)核心解析

元注解是专门用于定义其他注解的注解,共有 5 种标准元注解。理解它们是掌握自定义注解的关键。


1. @Target:指定注解作用目标

作用:控制注解可以应用在哪些程序元素上
参数ElementType[] 数组,常用值:

  • TYPE:类、接口、枚举
  • FIELD:字段(包括枚举常量)
  • METHOD:方法
  • PARAMETER:方法参数
  • CONSTRUCTOR:构造函数
  • LOCAL_VARIABLE:局部变量
  • ANNOTATION_TYPE:注解类型本身
  • PACKAGE:包声明

示例

@Target(ElementType.METHOD) // 仅作用于方法
public @interface Loggable {
    String value() default "";
}

2. @Retention:定义注解生命周期

作用:控制注解被保留到哪个阶段
参数RetentionPolicy 枚举:

  • SOURCE:仅保留在源码中,编译时丢弃(如 @Override
  • CLASS:保留到字节码文件,但运行时不可见(默认)
  • RUNTIME:保留到运行时,可通过反射读取

示例

@Retention(RetentionPolicy.RUNTIME) // 运行时可见
public @interface Audit {
    String operator() default "SYSTEM";
}

3. @Documented:生成文档时包含注解

作用:使用 javadoc 生成 API 文档时,保留注解信息

示例

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiVersion {
    String version();
}

4. @Inherited:允许子类继承父类注解

作用:当注解作用在类上时,子类自动继承该注解
注意:仅对类注解有效,对方法/字段注解无效

示例

@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface DeprecatedApi {
    String replacement() default "";
}

@DeprecatedApi(replacement = "NewService")
class OldService {}

class NewService extends OldService {} // 自动继承 @DeprecatedApi

5. @Repeatable(Java 8+):允许重复应用

作用:解决同一注解不能重复作用于同一目标的问题
实现:需配合容器注解使用

示例

// 定义可重复的注解
@Repeatable(Authorities.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authority {
    String role();
}

// 容器注解
@Retention(RetentionPolicy.RUNTIME)
public @interface Authorities {
    Authority[] value();
}

// 使用示例
@Authority("admin")
@Authority("user")
class UserController {}

三、自定义注解实战案例

场景:实现方法执行时间统计

  1. 定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TimeLog {
    String description() default "";
}
  1. 通过 AOP 实现切面(需 Spring AOP 或 AspectJ):
@Aspect
@Component
public class TimeLogAspect {
    
    @Around("@annotation(timeLog)")
    public Object logTime(ProceedingJoinPoint joinPoint, TimeLog timeLog) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long duration = System.currentTimeMillis() - start;
        System.out.printf("%s 执行耗时: %d ms%n", 
            timeLog.description(), duration);
        return result;
    }
}
  1. 使用注解
@Service
public class OrderService {
    
    @TimeLog(description = "创建订单操作")
    public void createOrder(Order order) {
        // 业务逻辑
    }
}

四、最佳实践建议

  1. 明确生命周期:根据需求选择 SOURCE/CLASS/RUNTIME
  2. 精准定位目标:避免过度使用 ElementType.TYPE
  3. 提供默认值:简化注解使用(如 String value() default ""
  4. 组合元注解:通过组合实现复杂行为(如 @Documented + @Inherited
  5. 防御性编程:对注解参数进行空值检查

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值