spring注解(一)——Annotation注解基础

Annotation

  • 概述
    • Annotation获取
      • getAnnotation
      • annotationData
      • createAnnotationData
      • 解析注解
    • annotationType()和getClass()
  • Spring注解
    • 注解编程模型
  • @AliasFor
    • 别名
      • 显式别名
      • 隐式别名
      • 隐式别名传递
    • 属性覆盖
      • 显式覆盖
      • 隐式覆盖
      • 显式覆盖传递(Transitive Explicit Overrides)

概述

Annotation获取

Annotation也是对象,通过Class的getAnnotation,它返回的annotationData().annotations

getAnnotation

 public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
        Objects.requireNonNull(annotationClass);

        return (A) annotationData().annotations.get(annotationClass);
    }

annotationData

annotationData的创建,parseAnnotations前两个都是native方法,由他们创建了Annotation对象。然后以注解类class为key,注解对象为value放入annotationsmap中,所以我们取的时候就是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;
            }
        }
    }

createAnnotationData

 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);
    }

解析注解

var0getRawAnnotations注解来源类的字节码

 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;
    }

annotationType()和getClass()

/**
注解
*/
@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对象。
spring注解(一)——Annotation注解基础_第1张图片
spring注解(一)——Annotation注解基础_第2张图片
spring注解(一)——Annotation注解基础_第3张图片

Spring注解

注解编程模型

因为注解没有implements 和 extends,在面向对象编程中不是那么顺畅。Spring为了简化注解编程编程,提供了四种注解编程模型:

  • 元注解(Meta-Annotations),注解上的注解。同名属性会被覆盖
  • 模式注解(Stereotype Annotations):扮演某种职责或角色
  • 组合注解(Composed Annotations):@SpringBootApplication 是 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 三个注解的组合注解。
  • 属性别名和覆盖

@AliasFor

@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声明后互为别名,那么它们是显式别名。@ContextConfigurationlocationsvalue互为显式别名。@AliasFor自身的valueattribute也是互为显式别名

public @interface ContextConfiguration {
  
    @AliasFor("locations")
    String[] value() default {};
  
    @AliasFor("value")
    String[] locations() default {};
  
    // ...
}

隐式别名

如果一个注解中的两个或者更多成员通过@AliasFor声明去覆盖元注解的同一个成员,它们就是元注解成员属性的隐式别名。valueJavaScriptsxmlFiles都互为隐式别名。是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 声明去覆盖元注解中的不同成员,但是实际上因为覆盖的传递性导致最终覆盖的是元注解中的同一个成员。
spring注解(一)——Annotation注解基础_第4张图片

@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@XmlConfigxmlFiles属性显示覆盖。

@ContextConfiguration
public @interface XmlConfig {
   @AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
   String[] xmlFiles();
 }

隐式覆盖

是一种命名规约。一个注解和它的元注解有相同的属性名。隐含着元注解的这个属性被覆盖。@XmlConfiglocations属性隐式覆盖元注解@ContextConfigurationlocations属性

@ContextConfiguration
public @interface XmlConfig {
   String[] locations();
 }

显式覆盖传递(Transitive Explicit Overrides)

spring注解(一)——Annotation注解基础_第5张图片

你可能感兴趣的:(Spring)