首页 > 基础资料 博客日记
JAVA注解处理
2025-07-27 22:00:02基础资料围观10次
元注解
JDK元注解
@Target
指定注解可以应用的目标(如类、方法、字段等)。
常用取值(ElementType
枚举):
TYPE
:类、接口、枚举FIELD
:字段METHOD
:方法PARAMETER
:方法参数CONSTRUCTOR
:构造函数ANNOTATION_TYPE
:注解(用于定义元注解)
示例:
@Target(ElementType.METHOD) // 只能用在方法上
public @interface MyAnnotation {}
@Retention
指定注解的生命周期(源码、编译期、运行时)。
常用取值(RetentionPolicy
枚举):
SOURCE
:仅源码保留(如@Override
,编译后丢弃)CLASS
:编译期保留(默认,但运行时不可见)RUNTIME
:运行时保留(可通过反射读取)
示例:
@Retention(RetentionPolicy.RUNTIME) // 运行时可通过反射获取
public @interface MyAnnotation {}
@Documented
标记注解是否包含在 JavaDoc 中。
示例:
@Documented // 生成的 JavaDoc 会显示此注解
public @interface MyAnnotation {}
@Inherited
允许子类继承父类的注解(仅对 @Target(ElementType.TYPE)
有效)。
示例:
@Inherited // 子类会继承父类的此注解
public @interface MyAnnotation {}
@MyAnnotation
class Parent {}
class Child extends Parent {} // Child 也拥有 @MyAnnotation
@Repeatable(Java 8+)
允许同一注解在同一个位置重复使用。
示例:
@Repeatable(MyAnnotations.class) // 可重复使用
public @interface MyAnnotation {
String value();
}
@MyAnnotation("A")
@MyAnnotation("B") // 合法
class MyClass {}
@Native(Java 8+)
用于指示某个字段可能被本地代码(如 JNI)引用。
用法:
- 不强制约束:@Native 仅是一个标记,不改变字段的访问权限或行为。
- 非运行时注解:编译后会被丢弃,无法通过反射获取。
- 仅限字段:不能用于方法、类或其他目标。
示例:
public class NativeExample {
@Native
public static final int BUFFER_SIZE = 1024; // 可能被本地代码使用
static {
System.loadLibrary("nativeLib"); // 加载本地库
}
public native void nativeMethod(); // 本地方法声明
}
Spring 扩展的元注解
@AliasFor
定义注解属性的别名(如 @RequestMapping.path
和 @RequestMapping.value
)。
示例:
public @interface MyAnnotation {
@AliasFor("path") // value 和 path 是别名
String value() default "";
@AliasFor("value")
String path() default "";
}
@Component(间接元注解)
标记一个类为 Spring 组件(@Service
、@Controller
等均元标注了 @Component
)。
示例:
@Component // @Service 元标注了 @Component
public @interface Service {}
@Indexed(Spring 5+)
加速类路径扫描,提升启动性能。
示例:
@Indexed // 标记为可索引的组件
@Component
public class MyComponent {}
Spring工具类
AnnotatedElementUtils
findMergedAnnotation(AnnotatedElement, Class)
这个方法完全支持@AliasFor
。例如@PostMapping
中嵌套了@RequestMapping
注解,并且各属性依赖于它的属性。通过以下代码可以获取@PostMapping
的path属性,且path和value的值互通。
示例:
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(clazz, RequestMapping.class);
System.out.println(Arrays.toString(requestMapping.path()));
参考来源:org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder#getClassMapping
private static String getClassMapping(Class<?> controllerType) {
Assert.notNull(controllerType, "'controllerType' must not be null");
RequestMapping mapping = AnnotatedElementUtils.findMergedAnnotation(controllerType, RequestMapping.class);
if (mapping == null) {
return "/";
}
String[] paths = mapping.path();
if (ObjectUtils.isEmpty(paths) || !StringUtils.hasLength(paths[0])) {
return "/";
}
if (paths.length > 1 && logger.isTraceEnabled()) {
logger.trace("Using first of multiple paths on " + controllerType.getName());
}
return paths[0];
}
AnnotationUtils
getAnnotation(Annotation, Class)
对于元注解的支持没有AnnotatedElementUtils
强大,不支持元注解@AliasFor
在嵌套注解中属性的关联,仅能获取当前注解的@AliasFor
关联属性。以下代码可以获取@RequestMapping
的path属性,且path和value的值互通。但不能通过获取@RequestMapping
来获取@PostMapping
中配置的path属性值。
示例:
RequestMapping requestMapping = AnnotationUtils.getAnnotation(clazz, RequestMapping.class);
System.out.println(Arrays.toString(requestMapping.path()));
不支持递归父级,递归处理需使用
findAnnotation(...)
相关的方法
findAnnotation(AnnotatedElement, Class)
若指定的方法或者类上没有找到对应的注解,则会递归查找父类或者接口对应的元素上有无该注解。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
上一篇:探索C++世界的奥秘:从核心特性到高效开发实践
下一篇:没有了