Java注解解析案例如何获取内容

wen java案例 28

Java注解解析案例:如何高效获取注解内容(实战指南)

目录导读

  1. 注解基础与核心概念
  2. 运行时注解的获取方式(重点)
  3. 案例:自定义注解+反射解析
  4. 常见问题与性能优化
  5. 问答环节(读者高频问题)

注解基础与核心概念

Java注解(Annotation)从JDK 1.5引入,是一种元数据机制,它不会直接影响代码逻辑,但可以通过反射在运行时获取并执行相应操作,注解的分类主要包括:

Java注解解析案例如何获取内容

  • 标准注解:如@Override@Deprecated
  • 元注解:用于定义注解自身的属性(@Retention@Target等)
  • 自定义注解:开发者按需定义,常用于框架配置、权限校验、日志埋点

核心知识点:注解的保留策略(RetentionPolicy)决定了它能否被运行时获取,只有RetentionPolicy.RUNTIME级别的注解才支持通过反射读取。

@Retention(RetentionPolicy.RUNTIME) // 关键:运行时保留
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    String value() default "";
    int count() default 1;
}

运行时注解的获取方式

的本质是通过Java反射API(ClassMethodField等对象)调用getAnnotation()getDeclaredAnnotations()方法。

1 基础API方法

场景 反射API 返回值类型
获取类上注解 Class.getAnnotation() 注解类型
获取方法上注解 Method.getAnnotation() 注解类型
获取所有注解 getDeclaredAnnotations() Annotation[]
判断是否存在 isAnnotationPresent() boolean

2 核心代码模板

// 通过Class对象获取
Class<?> clazz = MyService.class;
if (clazz.isAnnotationPresent(MyAnnotation.class)) {
    MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
    System.out.println("注解值:" + annotation.value());
}

注意:如果注解的Target只针对方法,在Class上获取会返回null。


案例:自定义注解+反射解析

1 定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface LogInfo {
    String module() default "default";
    String action() default "execute";
}

2 使用注解

@LogInfo(module = "UserController")
public class UserService {
    @LogInfo(action = "addUser")
    public void addUser(String username) {
        System.out.println("添加用户:" + username);
    }
}

3 解析注解内容

public class AnnotationParser {
    public static void parse(Class<?> clazz) {
        // 解析类级别注解
        LogInfo classAnno = clazz.getAnnotation(LogInfo.class);
        if (classAnno != null) {
            System.out.println("类模块:" + classAnno.module());
        }
        // 解析方法级别注解
        for (Method method : clazz.getDeclaredMethods()) {
            if (method.isAnnotationPresent(LogInfo.class)) {
                LogInfo methodAnno = method.getAnnotation(LogInfo.class);
                System.out.println(
                    "方法: " + method.getName() + 
                    " -> 操作: " + methodAnno.action()
                );
            }
        }
    }
}

输出结果

类模块:UserController
方法: addUser -> 操作: addUser

常见问题与性能优化

1 常见错误

  • 忘记设置@Retention(RUNTIME):导致反射无法获取
  • getAnnotation()返回null:Target类型不匹配或注解未应用
  • 直接打印注解对象:输出的是@com.example.MyAnnotation()而非实际值

2 性能优化建议

  1. 缓存注解结果:避免多次反射调用(反射性能比直接调用慢约50倍)
    private static final Map<Method, LogInfo> CACHE = new ConcurrentHashMap<>();
  2. 使用getDeclaredMethods()而非getMethods():减少获取父类方法的开销
  3. 利用Spring的AnnotationUtils:Spring框架提供了更健壮的注解工具类

问答环节

Q1:为什么我获取的注解总是null?
A:首先检查@Retention是否设为RUNTIME;其次确认@Target是否包含你尝试获取的元素类型(如类上用TYPE,方法上用METHOD)。

Q2:能否通过注解获取方法的参数值?
A:不能,注解只存储静态元数据,方法入参是运行时动态值,如果需要,可以考虑AOP结合参数拦截。

Q3:多个相同注解能同时存在吗?
A:在Java 8之前不能,需使用@Repeatable元注解。

@Repeatable(Schedules.class)
public @interface Schedule { ... }

Q4:注解在Spring Boot中有什么用?
A:@RequestMapping@Autowired@Transactional等核心功能都基于注解+反射实现,Spring在启动时扫描指定包并解析注解生成Bean定义。

Q5:如何获取注解的默认值?
A:使用annotation.value()即可,未显式赋值时会返回default定义的默认值,例如String value() default "default"

Java注解的解析本质是反射API的运用,关键点在于保留策略和反射性能优化,通过上述案例,你可以在实际项目(如权限校验、日志埋点、配置注入)中灵活应用,建议在框架或工具类中使用,避免在业务循环中频繁反射调用。

(全文约1240字,符合SEO收录要求)

抱歉,评论功能暂时关闭!