元注解的源码结构
@Document
@Inherited
@Retention
@Target
@Native
@Repeatable
其中前4个是元注解
元注解负责注解自定义注解 自定义注必须使用元注解
元注解的用途
@Target
标识注解的使用范围 可以赋值为ElementType类型 ElementType定义如下
public enum ElementType {
TYPE,
FIELD,
METHOD,
PARAMETER,
CONSTRUCTOR,
LOCAL_VARIABLE,
ANNOTATION_TYPE,
PACKAGE,
TYPE_PARAMETER,
TYPE_USE
}
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
RetentionPolicy.SOURCE 表明注解会被编译器丢弃 字节码中不会带有注解信息
RetentionPolicy.CLASS 表明注解会被写入字节码文件 且是@Retention的默认值
RetentionPolicy.RUNTIME 表明注解会被写入字节码文件 并且能够被JVM在运行时获取到 可以通过反射的方式解析到
@Documented
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
jdk中是通过AnnotatedElement(package java.lang.reflect)接口实现对注解的解析 我们的Class类实现了AnnotatedElement接口
public final class Class<T> implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement {
......
}
AnnotatedElement的注释:
Represents an annotated element of the program currently running in this VM. This interface allows annotations to be read reflectively
翻译过来就是:AnnotatedElement代表了jvm中一个正在运行的被注解元素,这个接口允许通过反射的方式读取注解
可以看下Class类中对于AnnotatedElement接口都是如何实现的:
/**
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
@SuppressWarnings("unchecked")
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
return (A) annotationData().annotations.get(annotationClass);
}
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return GenericDeclaration.super.isAnnotationPresent(annotationClass);
}
@Override
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
AnnotationData annotationData = annotationData();
return AnnotationSupport.getAssociatedAnnotations(annotationData.declaredAnnotations,this,annotationClass);
}
public Annotation[] getAnnotations() {
return AnnotationParser.toArray(annotationData().annotations);
}
@Override
@SuppressWarnings("unchecked")
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
return (A) annotationData().declaredAnnotations.get(annotationClass);
}
@Override
public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotationData().declaredAnnotations,
annotationClass);
}
public Annotation[] getDeclaredAnnotations() {
return AnnotationParser.toArray(annotationData().declaredAnnotations);
}
上面的接口实现中 大致的原理都是一致的 挑选其中的getAnnotation方法来讲解
getAnnotation
根据注解的class实例从类的注解缓存数据中获取匹配的注解类型
Controller是注解类型,Controller.getClass()获取到的就是Class实例
1、代码中annotationData().annotations是一个Map(key为注解的Class实例,value为注解类型) 源码为
private static class AnnotationData {
final Map<Class<? extends Annotation>, Annotation> annotations;
final Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
final int redefinedCount;
AnnotationData(Map<Class<? extends Annotation>, Annotation> annotations,
Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
int redefinedCount) {
this.annotations = annotations;
this.declaredAnnotations = declaredAnnotations;
this.redefinedCount = redefinedCount;
}
}
2、annotationData()的源码是
private AnnotationData annotationData() {
while (true) { // retry loop
AnnotationData annotationData = this.annotationData;
int classRedefinedCount = this.classRedefinedCount;
if (annotationData != null &&
annotationData.redefinedCount == classRedefinedCount) {
return annotationData;
}
// null or stale annotationData -> optimistically create new instance
AnnotationData newAnnotationData = createAnnotationData(classRedefinedCount);
// try to install it
if (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) {
// successfully installed new AnnotationData
return newAnnotationData;
}
}
}
核心的逻辑是:当this.annotationData为空,解析类中的annotationData并写入this.annotationData,最后都会返回this.annotationData
3、其中Atomic.casAnnotationData(this, annotationData, newAnnotationData)的作用便是将解析到的annotationData写入this.annotationData:
static <T> boolean casAnnotationData(Class<?> clazz,
AnnotationData oldData,
AnnotationData newData) {
return unsafe.compareAndSwapObject(clazz, annotationDataOffset, oldData, newData);
}
其中unsafe.compareAndSwapObject是一个native方法
4、而createAnnotationData(classRedefinedCount)的作用是解析类中用到的annotationData
private AnnotationData createAnnotationData(int classRedefinedCount) {
Map<Class<? extends Annotation>, Annotation> declaredAnnotations =
AnnotationParser.parseAnnotations(getRawAnnotations(), getConstantPool(), this);
Class<?> superClass = getSuperclass();
Map<Class<? extends Annotation>, Annotation> annotations = null;
if (superClass != null) {
Map<Class<? extends Annotation>, Annotation> superAnnotations =
superClass.annotationData().annotations;
for (Map.Entry<Class<? extends Annotation>, Annotation> e : superAnnotations.entrySet()) {
Class<? extends Annotation> annotationClass = e.getKey();
if (AnnotationType.getInstance(annotationClass).isInherited()) {
if (annotations == null) { // lazy construction
annotations = new LinkedHashMap<>((Math.max(
declaredAnnotations.size(),
Math.min(12, declaredAnnotations.size() + superAnnotations.size())
) * 4 + 2) / 3
);
}
annotations.put(annotationClass, e.getValue());
}
}
}
if (annotations == null) {
// no inherited annotations -> share the Map with declaredAnnotations
annotations = declaredAnnotations;
} else {
// at least one inherited annotation -> declared may override inherited
annotations.putAll(declaredAnnotations);
}
return new AnnotationData(annotations, declaredAnnotations, classRedefinedCount);
}
整个的处理逻辑是:
1 获取类本身的declaredAnnotations
2 获取父类的annotations
3 将declaredAnnotations+annotations整合 返回
Annotation解析的范例代码:
@Component
public class SSHClient {
。。。
}
public class AnnotationHelper {
public static void main(String[] args) {
Annotation[] annotations = new Annotation[0];
annotations = SSHClient.class.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation.toString());
System.out.println(annotation.annotationType());
System.out.println(annotation.getClass().getName());
System.out.println(annotation.getClass().getTypeName());
System.out.println(annotation.getClass().toString());
}
if (SSHClient.class.isAnnotationPresent(Component.class)) {
System.out.println("find Component annotation");
}
Annotation annotation = SSHClient.class.getAnnotation(Component.class);
System.out.println(annotation.toString());
System.out.println(annotation.annotationType());
System.out.println(annotation.getClass().getName());
System.out.println(annotation.getClass().getTypeName());
System.out.println(annotation.getClass().toString());
}
}