您当前的位置: 首页 > 

java持续实践

暂无认证

  • 1浏览

    0关注

    746博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

注解底层实现原理

java持续实践 发布时间:2021-02-21 17:07:32 ,浏览量:1

文章目录
      • 注解获取属性值的底层实现
      • 注解的工作原理

注解获取属性值的底层实现

JVM会为注解生成代理对象. 这一节的文章中提到的获取注解信息的代码 https://javaweixin6.blog.csdn.net/article/details/113914653 注意注解的生命周期都要设置为runtime 程序运行时, 设置如下的jvm参数, 保存生成的代理对象成为文件 -Djdk.proxy.ProxyGenerator.saveGeneratedFiles=true 只获取成员属性的值. 运行上面的main方法后 , 生成的代码如下 在这里插入图片描述 在生成的代理对象中, 可以看到其中一个是实现了PersonInfoAnnotation这个注解的. 这个代理对象声明了9个静态的Method 在这里插入图片描述 这8个静态的Method, 对应了如下的内容, 除了toString hashCode 等之外, 即声明在注解中的方法.

 static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m6 = Class.forName("demo.annotation.PersonInfoAnnotation").getMethod("language");
            m5 = Class.forName("demo.annotation.PersonInfoAnnotation").getMethod("name");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("demo.annotation.PersonInfoAnnotation").getMethod("gender");
            m4 = Class.forName("demo.annotation.PersonInfoAnnotation").getMethod("age");
            m7 = Class.forName("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());
        }
    }

在生成的代理对象中, 注解的每一个成员方法, 都会在代理对象中有对应的方法, 例如下图的language 方法和name 方法. 其中super是Proxy 代理对象. 如下图所示 在这里插入图片描述 在这里插入图片描述 在代理类中的super.h.invoke中的h是InvocationHandler. 在这里插入图片描述 调用的是InvocationHandler 对象的invoke方法. 在这里插入图片描述 jvm启动的时候, 加一个额外的参数. -XX:+TraceClassLoading 用于打印出所有加载的类. 在控制台打印的信息中, 可以看到加载了AnnotationInvocationHandler 类. 在这里插入图片描述 AnnotationInvocationHandler 类实现了InvocationHandler 接口. 在这里插入图片描述 程序运行的时候, 会执行AnnotationInvocationHandler类中的invoke方法. 在这里插入图片描述 debug运行程序, 断点打在AnnotationInvocationHandler类中的invoke方法 中, 可以看到memberValues中, 可以获取到注解中的值. 在这里插入图片描述 memberValues 的本质是一个map, key的注解的方法名, 值就是给注解赋予的值. 在这里插入图片描述

注解的工作原理
  • 通过键值对的方式为注解的属性赋值. 如下图所示就是通过键值对的方式赋值 在这里插入图片描述
  • 编译器会检查注解的使用范围. 将注解的信息, 写入元素的属性表
  • 程序运行时, JVM将RUNTIME 的所有注解属性都取出最终存入map里.
  • JVM会创建AnnotationInvocationHandler 实例, 并传递上一步的map
  • JVM会使用JDK动态代理为注解生成代理类, 并初始化AnnotationInvocationHandler
  • 调用invoke方法, 通过传入方法名, 返回注解对应的属性值.
关注
打赏
1658054974
查看更多评论
立即登录/注册

微信扫码登录

0.0394s