Annotation
也是对象,通过Class的getAnnotation,它返回的annotationData().annotations
。
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
return (A) annotationData().annotations.get(annotationClass);
}
annotationData的创建,parseAnnotations前两个都是native方法,由他们创建了Annotation对象。然后以注解类class为key,注解对象为value放入annotations
map中,所以我们取的时候就是clazz.getAnnotation(xxx.class)
Class.AnnotationData
是一个注解缓存类,用于缓存该类的注解信息。类比ReflectionData
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;
}
}
}
private AnnotationData createAnnotationData(int classRedefinedCount) {
//1.解析当前类的注解
Map<Class<? extends Annotation>, Annotation> declaredAnnotations =
AnnotationParser.parseAnnotations(getRawAnnotations(), getConstantPool(), this);
//2.获取父类当前类的
Class<?> superClass = getSuperclass();
Map<Class<? extends Annotation>, Annotation> annotations = null;
if (superClass != null) {//父类存在
//3.获取父类上的注解
Map<Class<? extends Annotation>, Annotation> superAnnotations =
superClass.annotationData().annotations;
//3.1遍历注解
for (Map.Entry<Class<? extends Annotation>, Annotation> e : superAnnotations.entrySet()) {
//3.2获取注解类型
Class<? extends Annotation> annotationClass = e.getKey();
//3.3注解标注了isInherited,可以被继承
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
);
}
//放入注解map
annotations.put(annotationClass, e.getValue());
}
}
}
//3.4不能继承,直接注解映射赋值给注解map
if (annotations == null) {
// no inherited annotations -> share the Map with declaredAnnotations
annotations = declaredAnnotations;
} else {
// at least one inherited annotation -> declared may override inherited
/**至少有一个可继承注解,把直接注解映射加入到注解map,重复注解被当前注解覆盖
* map的同key覆盖原理
*/
annotations.putAll(declaredAnnotations);
}
//3.5把注解映射封装到注解缓存返回
return new AnnotationData(annotations, declaredAnnotations, classRedefinedCount);
}
var0
是getRawAnnotations
注解来源类的字节码
private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2(byte[] var0, ConstantPool var1, Class<?> var2, Class<? extends Annotation>[] var3) {
LinkedHashMap var4 = new LinkedHashMap();
//把注解最初来源类封装成字节缓冲器
ByteBuffer var5 = ByteBuffer.wrap(var0);
//获取字节码前16位,前面六个字节是属性名称索引和属性值的长度
int var6 = var5.getShort() & '\uffff';
for(int var7 = 0; var7 < var6; ++var7) {
Annotation var8 = parseAnnotation2(var5, var1, var2, false, var3);
if (var8 != null) {
Class var9 = var8.annotationType();
if (AnnotationType.getInstance(var9).retention() == RetentionPolicy.RUNTIME && var4.put(var9, var8) != null) {
throw new AnnotationFormatError("Duplicate annotation for class: " + var9 + ": " + var8);
}
}
}
return var4;
}
/**
注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnotation {
String value() default "haha";
}
/**
被注解的类
*/
@MyAnotation
public class Test {
public static void main(String[] args) {
Test t = new Test();
//返回的是注解对象:@MyAnotation("haha"),是一个jdk动态代理
Annotation at = t.getClass().getAnnotation(MyAnotation.class);
//返回注解对象的类型:interface MyAnotation
Class<? extends Annotation> a = at.annotationType();
//返回注解的Class对象:class com.sun.proxy.$Proxy1
Class<?> c = at.getClass();
System.out.println(a);
System.out.println(c);
}
}
getAnnotation返回的是注解的代理类对象,通过这个代理对象可以获取真正的注解(也是注解类型),也可通过代理对象的getClass()获取代理类的Class对象。
因为注解没有implements 和 extends,在面向对象编程中不是那么顺畅。Spring为了简化注解编程编程,提供了四种注解编程模型:
@AliasFor
是属性别名、覆盖实现的基础。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface AliasFor {
@AliasFor("attribute")
String value() default "";
@AliasFor("value")
String attribute() default "";
//需要覆盖的注解类型。同一注解内部使用AliasFor可以省略 annotation 属性
Class<? extends Annotation> annotation() default Annotation.class;
}
一个注解中的两个成员通过@AliasFor声明后互为别名,那么它们是显式别名。@ContextConfiguration
中locations
和value
互为显式别名。@AliasFor
自身的value
和attribute
也是互为显式别名
public @interface ContextConfiguration {
@AliasFor("locations")
String[] value() default {};
@AliasFor("value")
String[] locations() default {};
// ...
}
如果一个注解中的两个或者更多成员通过@AliasFor声明去覆盖元注解的同一个成员,它们就是元注解成员属性的隐式别名。value
、JavaScripts
、xmlFiles
都互为隐式别名。是locations
属性的显示覆盖。主要目的是元注解属性覆盖。
@ContextConfiguration
public @interface MyConfig {
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] value() default {};
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] javaScripts() default {};
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] xmlFiles() default {};
}
如果一个注解中的两个或者更多成员通过@AliasFor 声明去覆盖元注解中的不同成员,但是实际上因为覆盖的传递性导致最终覆盖的是元注解中的同一个成员。
@MyConfig
public @interface javaOrXmlConfig {
@AliasFor(annotation = MyConfig.class, attribute = "javaScripts")
String[] jav() default {};
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] xml() default {};
}
如果一个注解中的成员通过@AliasFor声明去覆盖元注解属性。元注解@ContextConfiguration
的属性locations
被@XmlConfig
的xmlFiles
属性显示覆盖。
@ContextConfiguration
public @interface XmlConfig {
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] xmlFiles();
}
是一种命名规约。一个注解和它的元注解有相同的属性名。隐含着元注解的这个属性被覆盖。@XmlConfig
的locations
属性隐式覆盖元注解@ContextConfiguration
的locations
属性
@ContextConfiguration
public @interface XmlConfig {
String[] locations();
}