美文网首页
注解Annotation

注解Annotation

作者: 蜗牛写java | 来源:发表于2019-03-24 22:34 被阅读0次

    注解Annotation

    概念相关

    JDK5开始,java增加了对元数据(MetaData)的支持,也就是Annotation。

    Annotation其实就是代码里的特殊标记,这些编辑可以在编译、类加载、运行的时候被读取,并执行相应的处理。可以实现不改变原有逻辑的情况下,源代码中嵌入补充信息。

    它是一种程序元素(类、方法、成员变量等)的元数据,不会影响程序逻辑。

    注解分类

    根据注解参数的个数分类

    1. 标记注解:一个没有成员定的以的Annotation;这种Annotation类型仅适用自身的存在与否来为我们提供信息。
    2. 单值注解:只存在 value = "xxx";通常@Annotation("xxx");value=可以省略
    3. 完整注解

    根据注解适用方法和用途分类

    1. JDK内置系统注解
    2. 元注解:标记其它注解的注解
    3. 自定义注解

    JDK常用的注解

    • @Override : 重写方法

    • @Deprecated : 表示某个程序元素(类、方法等)已经过时

    • @SuppressWarnings : 抑制编译器警告

    • @SafeVarargs : 堆污染警告(java7出现)

      堆污染:把一个不带泛型的对象赋给一个带泛型的变量

      List list = new ArrayList<Integer>();
      list.add(20);
      List<String> ls = list;
      System.out.println(ls.get(0));
      
    • @Functionallnterface : 函数式接口

      接口中只有一个抽象方法,该接口就是函数式接口,@FunctionalInterface 就是用来执行某个接口必须是函数式接口。

    JDK元Annotation

    5个元Annotation 用于修饰其它Annotation的定义

    • @Retention : 用于执行被修饰的Annotation可以保留多长时间

      value的值:

      ​ RetentionPolicy.CLASS : 编译器把Annotation记录在class中,当运行java程序时,jvm获取不到,默认值

      ​ RetentionPolicy.RUNTIME:编译器把Annotation记录在class中,当运行java程序时,jvm可以获取到Annotation信息,程序可以通过反射获取Annotation信息

      ​ RetentionPolicy.SOURCE:编译器把Annotation记录在源码中,class中丢失该Annotation

      @Retention(value=RetentionPolicy.RUNTIME)
      public @interface Test{}
      

      说明:如果使用注解只为value成员变量指定值时,可以括号内直接指定value,如:

      @Retention(RetentionPolicy.RUNTIME)
      public @interface Test{}
      
    • @Target

      @Target 只能修饰一个Annotation,用于指定被修饰的Annotation能用于修饰在什么地方

      value 说明
      ElementType.ANNOTATION_TYPE 只能修饰Annotation
      ElementType.CONSTRUCTOR 构造器
      ElementType.FIELD 成员变量
      ElementType.LOCAL_VARIABLE 局部变量
      ElementType.METHOD 方法
      ElementType.PACKAGE
      ElementType.PARAMETER 参数
      ElementType.TYPE 类、接口、枚举
    • @Documented

      用于指定被@Documented修饰的annotation修饰的类被javadoc工具提取成文档

    • @Inherited

      用于指定被@Inherited修饰的annotation修饰的类,具有继承性;如类A使用了@xxx (@xxx被@Inherited修饰),那么继承类A的子类a会自动被@xxx修饰(无需显示手动写出)

    自定义注解

    格式:

    public @interface AnnotationName { ... }

    说明:

    使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成的。在定义注解时候,不能继承其它的注解或者接口。

    注解支持的数据类型

    1. 基本类型(不支持包装类型)
    2. String类型
    3. Class类型
    4. enum类型
    5. Annotation类型
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AnnotationDemo {
        int value() default 0;
        String name() default "";
    }
    

    注解的运行原理

    注解本质是一个继承了Annotation的特殊接口,其具体的实现类是java运行时生成的动态代理类(Debug是,可以看到动态代理对象$Proxy1,通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandlerinvoke方法。该方法会从memberValues 这个Map 中索引出对应的值。而memberValues 的来源是Java 常量池)。通过反射获取注解相关信息。

    注解处理类(AnnotatedElement;也叫注解处理器),获取注解信息。

    Annotation接口,代表注解的注解,是所有注解的父接口

    AnnotatedElement接口,代表程序中可以接受注解的程序元素;该接口也叫注解处理器;如图:

    AnnotatedElement-UML.png
    • <T extends Annotation> T getAnnotation(Class<T> annotationClass)

      返回程序元素上存在的指定类型的注解,若不存在,则返回null

    • Annotation[] getAnnotations()

      返回该程序元素上存在的所有注解

    • boolean is AnnotationPresent(Class<?extends Annotation> annotationClass)

      判断程序元素上是否包含指定类型的注解

    • Annotation[] getDeclaredAnnotations()

      返回直接存在于此元素上的所有注解(忽略继承的注解)

    获取注解的过程;也就是上述五个继承类中(注解处理器),getAnnotations 的过程:

    客户端代码:

    Field name = client.getClass().getDeclaredField("name");
    AnnotationDemo annotation = name.getAnnotation(AnnotationDemo.class);
    

    Field.java

    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
        Objects.requireNonNull(annotationClass);
        return annotationClass.cast(declaredAnnotations().get(annotationClass));
    }
    
    private synchronized  Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
            if (declaredAnnotations == null) {
                Field root = this.root;
                if (root != null) {
                    declaredAnnotations = root.declaredAnnotations();
                } else {
                    declaredAnnotations = AnnotationParser.parseAnnotations(
                            annotations,
                            sun.misc.SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()),
                            getDeclaringClass());
                }
            }
            return declaredAnnotations;
    

    AnnotationParser.class

    public static Map<Class<? extends Annotation>, Annotation> parseAnnotations(byte[] var0, ConstantPool var1, Class<?> var2) {
            if (var0 == null) {
                return Collections.emptyMap();
            } else {
                try {
                    return parseAnnotations2(var0, var1, var2, (Class[])null);
                } catch (BufferUnderflowException var4) {
                    throw new AnnotationFormatError("Unexpected end of annotations.");
                } catch (IllegalArgumentException var5) {
                    throw new AnnotationFormatError(var5);
                }
            }
        }
    
    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);
            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;
        }
    
     private static Annotation parseAnnotation2(ByteBuffer var0, ConstantPool var1, Class<?> var2, boolean var3, Class<? extends Annotation>[] var4) {
            int var5 = var0.getShort() & '\uffff';
            Class var6 = null;
            String var7 = "[unknown]";
    
            try {
                try {
                    var7 = var1.getUTF8At(var5);
                    var6 = parseSig(var7, var2);
                } catch (IllegalArgumentException var18) {
                    var6 = var1.getClassAt(var5);
                }
            } catch (NoClassDefFoundError var19) {
                if (var3) {
                    throw new TypeNotPresentException(var7, var19);
                }
    
                skipAnnotation(var0, false);
                return null;
            } catch (TypeNotPresentException var20) {
                if (var3) {
                    throw var20;
                }
    
                skipAnnotation(var0, false);
                return null;
            }
    
            if (var4 != null && !contains(var4, var6)) {
                skipAnnotation(var0, false);
                return null;
            } else {
                AnnotationType var8 = null;
    
                try {
                    var8 = AnnotationType.getInstance(var6);
                } catch (IllegalArgumentException var17) {
                    skipAnnotation(var0, false);
                    return null;
                }
    
                Map var9 = var8.memberTypes();
                LinkedHashMap var10 = new LinkedHashMap(var8.memberDefaults());
                int var11 = var0.getShort() & '\uffff';
    
                for(int var12 = 0; var12 < var11; ++var12) {
                    int var13 = var0.getShort() & '\uffff';
                    String var14 = var1.getUTF8At(var13);
                    Class var15 = (Class)var9.get(var14);
                    if (var15 == null) {
                        skipMemberValue(var0);
                    } else {
                        Object var16 = parseMemberValue(var15, var0, var1, var2);
                        if (var16 instanceof AnnotationTypeMismatchExceptionProxy) {
                            ((AnnotationTypeMismatchExceptionProxy)var16).setMember((Method)var8.members().get(var14));
                        }
    
                        var10.put(var14, var16);
                    }
                }
    
                return annotationForMap(var6, var10);
            }
        }
    
    public static Annotation annotationForMap(final Class<? extends Annotation> var0, final Map<String, Object> var1) {
            return (Annotation)AccessController.doPrivileged(new PrivilegedAction<Annotation>() {
                public Annotation run() {
                    //该句是重点;返回动态代理对象
                    return (Annotation)Proxy.newProxyInstance(var0.getClassLoader(), new Class[]{var0}, new AnnotationInvocationHandler(var0, var1));
                }
            });
        }
    
    class AnnotationInvocationHandler implements InvocationHandler, Serializable {
        private static final long serialVersionUID = 6182022883658399397L;
        private final Class<? extends Annotation> type;
        //该句是重点:对象池
        private final Map<String, Object> memberValues;
        private transient volatile Method[] memberMethods = null;
    
        AnnotationInvocationHandler(Class<? extends Annotation> var1, Map<String, Object> var2) {
            Class[] var3 = var1.getInterfaces();
            if (var1.isAnnotation() && var3.length == 1 && var3[0] == Annotation.class) {
                this.type = var1;
                this.memberValues = var2;
            } else {
                throw new AnnotationFormatError("Attempt to create proxy for a non-annotation type.");
            }
        }
    
        public Object invoke(Object var1, Method var2, Object[] var3) {
          
            }
        }
    

    相关文章

      网友评论

          本文标题:注解Annotation

          本文链接:https://www.haomeiwen.com/subject/rbnpvqtx.html