美文网首页
注解中获取属性值的底层原理

注解中获取属性值的底层原理

作者: 码而优则仕 | 来源:发表于2020-06-24 20:57 被阅读0次

    注解中获取属性值的底层原理

    Java里面万物皆为对象,注解也不例外,JVM会在运行时为我们生成中间对象。

    要获取JVM生成的中间对象,需要修改JVM的启动参数,才能获取到JVM为我们生成的中间对象。

    JDK8配置如下命令:

    JVMParamSetting.png

    执行如下程序:

    public class AnnotationParser {
    
        //解析类的注解
        public static void parseTypeAnnotation() throws Exception {
            Class target = Class.forName("com.yuns.demo.annotation.YunsCourse");
            System.out.println("=====获取类上注解=======");
            Annotation[] annotations = target.getAnnotations();
            for (Annotation annotation : annotations) {
                CourseInfoAnnotation courseInfoAnnotation = (CourseInfoAnnotation) annotation;
                System.out.println("课程名称 :" + courseInfoAnnotation.courseName());
                System.out.println("课程标签 :" + courseInfoAnnotation.courseTag());
                System.out.println("课程简介 :" + courseInfoAnnotation.courseProfile());
                System.out.println("课程序号 :" + courseInfoAnnotation.coursIendex());
    
            }
    
        }
    
        //解析成员变量的注解
        public static void parseFieldAnnotation() throws Exception {
            Class target = Class.forName("com.yuns.demo.annotation.YunsCourse");
            System.out.println("=====获取成员变量上的注解=======");
            Field[] fields = target.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(PersonInfoAnnotation.class)) {
                    PersonInfoAnnotation personInfoAnnotation = (PersonInfoAnnotation) field.getAnnotation(PersonInfoAnnotation.class);
                    System.out.println("姓名 :" + personInfoAnnotation.name());
                    System.out.println("年龄 :" + personInfoAnnotation.age());
                    System.out.println("精通语言 :" + personInfoAnnotation.language());
                    System.out.println("性别 :" + personInfoAnnotation.gender());
                }
            }
        }
    
        //解析成员方法的注解
        public static void parseMethodAnnotation() throws Exception {
            Class target = Class.forName("com.yuns.demo.annotation.YunsCourse");
            System.out.println("=====获取成员方法上的注解=======");
            Method[] methods = target.getDeclaredMethods();
            for (Method method : methods) {
                if (method.isAnnotationPresent(CourseInfoAnnotation.class)) {
                    CourseInfoAnnotation courseInfoAnnotation = (CourseInfoAnnotation) method.getAnnotation(CourseInfoAnnotation.class);
                    System.out.println("课程名称 :" + courseInfoAnnotation.courseName());
                    System.out.println("课程标签 :" + courseInfoAnnotation.courseTag());
                    System.out.println("课程简介 :" + courseInfoAnnotation.courseProfile());
                    System.out.println("课程序号 :" + courseInfoAnnotation.coursIendex());
                }
            }
        }
    
    
        public static void main(String args[]) throws Exception {
    //        parseTypeAnnotation();
            parseFieldAnnotation();
    //        parseMethodAnnotation();
        }
    }
    

    会在项目下生成com.sun.proxy文件夹,文件夹下就是JDK运行时动态代理生成的中间对象:

    //实现元注解Retention
    public final class $Proxy0 extends Proxy implements Retention {
        private static Method m1;
        private static Method m2;
        private static Method m4;
        private static Method m0;
        private static Method m3;
    
        public $Proxy0(InvocationHandler var1) throws  {
            super(var1);
        }
    
        public final boolean equals(Object var1) throws  {
            try {
                return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }
    
        public final String toString() throws  {
            try {
                return (String)super.h.invoke(this, m2, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        public final Class annotationType() throws  {
            try {
                return (Class)super.h.invoke(this, m4, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        public final int hashCode() throws  {
            try {
                return (Integer)super.h.invoke(this, m0, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        public final RetentionPolicy value() throws  {
            try {
                return (RetentionPolicy)super.h.invoke(this, m3, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        static {
            try {
                m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
                m2 = Class.forName("java.lang.Object").getMethod("toString");
                m4 = Class.forName("java.lang.annotation.Retention").getMethod("annotationType");
                m0 = Class.forName("java.lang.Object").getMethod("hashCode");
                m3 = Class.forName("java.lang.annotation.Retention").getMethod("value");
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }
    }
    
    public final class $Proxy1 extends Proxy implements PersonInfoAnnotation {
        private static Method m1;
        private static Method m4;
        private static Method m3;
        private static Method m2;
        private static Method m6;
        private static Method m5;
        private static Method m7;
        private static Method m0;
    
    public $Proxy1(InvocationHandler var1) throws  {
        super(var1);
    }
    
    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
    
    public final String[] language() throws  {
        try {
            return (String[])super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    
    public final String name() throws  {
        try {
            return (String)super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    
    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    
    public final String gender() throws  {
        try {
            return (String)super.h.invoke(this, m6, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    
    public final int age() throws  {
        try {
            return (Integer)super.h.invoke(this, m5, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    
    public final Class annotationType() throws  {
        try {
            return (Class)super.h.invoke(this, m7, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    
    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m4 = Class.forName("com.yuns.demo.annotation.PersonInfoAnnotation").getMethod("language");
            m3 = Class.forName("com.yuns.demo.annotation.PersonInfoAnnotation").getMethod("name");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m6 = Class.forName("com.yuns.demo.annotation.PersonInfoAnnotation").getMethod("gender");
            m5 = Class.forName("com.yuns.demo.annotation.PersonInfoAnnotation").getMethod("age");
            m7 = Class.forName("com.yuns.demo.annotation.PersonInfoAnnotation").getMethod("annotationType");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
    
    class AnnotationInvocationHandler implements InvocationHandler, Serializable {
    

    现在分析注解的工作原理

    • 首先通过键值对的形式为注解属性赋值

    @CourseInfoAnnotation(courseName = "注解学习", courseTag = "基础"
            , courseProfile = "学习注解全面知识")
    public class YunsCourse {
    
        @PersonInfoAnnotation(name = "wsq", language = {"Java", "C++"})
        private String author;
    
    
        @CourseInfoAnnotation(courseName = "Java基本知识学习", courseTag = "常识"
                , courseProfile = "学习框架必须的知识")
        public void getCourseInfo() {
    
        }
    }
    
    • 我们用注解修饰某个元素的时候,编译器在编译期扫描类的时候会检查注解的使用范围,然后判断注解添加的位置是否合理;如果合理的话会在Java编译成class文件的时候将注解信息写入元素的属性表。—注解就是在编译器编译的时候进行处理,写入class文件中。

    • 运行时JVM将一个类中所有生命周期时RUN的注解属性取出,并放到Map中

    • JVM会创建一个AnnotationInvocationHandler的实例,然后将存储注解属性的Map传递给这个实例

    private final Map<String, Object> memberValues;
    
    • JVM会使用动态代理为注解生成代理类,并初始化处理器(对应的InnovationHandler)。

    • 注解被JVM动态代理后,本质上就是一个代理类,通过调用invoke方法,通过传入方法名返回注解对应的属性名

    相关文章

      网友评论

          本文标题:注解中获取属性值的底层原理

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