Java自定义注解+反射解析核心是:①注解必须用@Retention(RUNTIME)和@Target声明;②反射需按Class/Method/Field层级获取并判空处理。

Java 自定义注解 + 反射解析,核心就两点:先定义一个带运行时生命周期的注解,再用反射在运行时读取它。关键不在写得多,而在元注解选得准、反射调用不漏掉检查。
定义注解要配齐两个必需元注解
@Retention(RetentionPolicy.RUNTIME) 和 @Target 是必须声明的。前者保证注解能活到运行期,后者限制它能标在哪(比如只允许标在方法上)。缺一不可,否则反射拿不到。
- 没加 @Retention(RUNTIME),反射调用 getAnnotation() 永远返回 null
- 没加 @Target,编译器不报错,但实际使用时可能被误标到字段或参数上,逻辑出错难排查
- 属性命名优先用 value(),单属性时可简化写法:@MyLog("save") 等价于 @MyLog(value = "save")
注解属性类型有严格限制
只能是基本类型、String、Class、枚举、注解,以及它们的一维数组。不能是 List、Map、自定义对象等复杂类型。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 想存多个字符串?用 String[] tags() default {};赋值时写 tags = {"user", "auth"}
- 想设默认值?直接写 age() default 18;不赋值时自动取这个值
- 返回类型写错(比如 int 而不是 Integer)会编译失败,注意包装类和基本类型都合法
反射解析要按元素层级逐级获取
类、方法、字段上的注解要分别用 Class、Method、Field 对象去取。不能指望一个方法扫全类——得自己遍历。
立即学习“Java免费学习笔记(深入)”;
- 查类上的注解:clazz.getAnnotation(MyService.class)
- 查所有 public 方法上的注解:for (Method m : clazz.getMethods()) { if (m.isAnnotationPresent(MyLog.class)) { ... } }
- 查私有方法需先调 setAccessible(true),否则 getDeclaredMethod() 会抛 IllegalAccessException
解析后别忘了做空判断和异常处理
getAnnotation() 返回 null 很常见(目标元素没标该注解),invoke() 可能抛 InvocationTargetException,这些不处理,程序容易崩。
- 先判 null:MyLog logAnno = method.getAnnotation(MyLog.class); if (logAnno != null) { ... }
- 调用被注解的方法时,用 try-catch 包住 invoke(),并处理 target 的初始化(比如 new 实例)
- 日志、权限、校验类注解,通常放在代理或 AOP 切面里统一处理,而不是每个地方手动反射

















