Java注解
注解的本质
注解本质是一个继承java.lang.annotation.Annotation的特殊接口,通过@interface关键字定义。
在编译阶段,java注解会被编译成一个继承 java.lang.annotation.Annotation 的特殊接口,并生成对应属性的抽象方法。
注解本质是一个继承自Annotation接口的动态代理对象,通过@interface关键字定义。
在运行阶段,通过JDK动态代理生成注解接口的实现类实例,通过反射调用AnnotationInvocationHandler.invoke()方法实现属性访问。
元注解
@Retention:定义注解生命周期。定义保留策略。- SOURCE:仅存在于源码(编译时丢弃,如@Override)。
- CLASS:保留在字节码(默认值,运行时不可读取)。
- RUNTIME:运行时可通过反射获取(框架常用)。
@Target:限制注解可应用的位置(类、方法、字段等)。@Inherited:允许子类继承父类的注解。@Documented:将注解包含在Javadoc中。
注解的存储与解析
- 字节码存储:注解信息以键值对形式存储在字节码的RuntimeVisibleAnnotations属性中。(编译时)
- AnnotationParser解析:JVM通过sun.reflect.annotation.AnnotationParser在运行时解析字节码中的注解数据,生成动态代理对象。(运行时)
- 常量池映射:注解的成员值通过常量池(Constant Pool)存储,代理类通过memberValues(Map结构)关联成员名与值。
动态代理与反射机制
- 代理对象生成:通过Proxy.newProxyInstance()生成注解接口的代理实例,绑定AnnotationInvocationHandler。
- 方法调用流程:
- 调用注解方法(如value())时,代理类触发AnnotationInvocationHandler.invoke()。
- 通过Class.getAnnotation()等反射API获取注解对象,实际返回的是动态代理实例。从memberValues中获取成员值并返回。
底层实现原理
Java注解的底层实现结合了元数据存储、反射和动态代理技术:
- 定义阶段:通过元注解声明行为和存储策略。
- 编译阶段:注解信息写入字节码。
- 运行时:通过反射和动态代理解析字节码,生成代理对象并操作成员值。
自定义注解
实现@interface,并用元注解@Retention与@Target修饰。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecutionTime {
String prefix() default "";
}
典型运用场景
- 日志记录:通过AOP在方法执行前后记录日志,结合自定义注解标记需记录的方法。
- 权限控制:在Controller方法上标注权限注解,结合拦截器或AOP实现动态权限校验。
- 数据校验:定义字段级注解(如@NotNull),通过Hibernate Validator等工具在运行时校验输入
通过反射API获取类、方法、字段等元素上的注解信息。
-
1.获取类上的注解
Class<?> clazz = MyClass.class; if (clazz.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class); System.out.println("Class Annotation Value: " + annotation.value()); } -
2.获取方法上的注解
Method method = clazz.getDeclaredMethod("myMethod"); if (method.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); System.out.println("Method Annotation Value: " + annotation.value()); } -
3.获取字段上的注解
Field field = clazz.getDeclaredField("myField"); if (field.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation annotation = field.getAnnotation(MyAnnotation.class); System.out.println("Field Annotation Value: " + annotation.value()); }

浙公网安备 33010602011771号