Java注解相关条记

打印 上一主题 下一主题

主题 895|帖子 895|积分 2685

注解

工作原理
  1. package com.breeze.rewrite_mybatis;
  2. import java.lang.annotation.*;
  3. @Retention(RetentionPolicy.RUNTIME)
  4. @Target({ElementType.METHOD})
  5. public @interface AliasFor {
  6.     @AliasFor("attribute")
  7.     String value() default "";
  8.     @AliasFor("value")
  9.     String attribute() default "";
  10. }
  11. package com.breeze.rewrite_mybatis;
  12. import java.lang.annotation.ElementType;
  13. import java.lang.annotation.Retention;
  14. import java.lang.annotation.RetentionPolicy;
  15. import java.lang.annotation.Target;
  16. @Retention(RetentionPolicy.RUNTIME)
  17. @Target(ElementType.TYPE)
  18. public @interface Table {
  19.     @AliasFor("value")
  20.     String tableName() default "";
  21.     @AliasFor("tableName")
  22.     String value();//value不能为空
  23. }
  24. package com.breeze.rewrite_mybatis;
  25. @Table("sys_user")
  26. public class User {
  27.     ...
  28. }
  29. package com.breeze.rewrite_mybatis;
  30. @Table("sys_user2")
  31. public class User2 {
  32.     ...
  33. }
  34. //在com.breeze.rewrite_mybatis.Main类下
  35. public static void main(String[] args){
  36.     User user1 = new User();
  37.     Table table = user1.getClass().getAnnotation(Table.class);
  38.     System.out.println(table.value());//sys_user
  39.     System.out.println(Table.class);//interface com.breeze.rewrite_mybatis.Table
  40.     System.out.println(table.getClass());//class com.sun.proxy.$Proxy1
  41.     System.out.println(table.annotationType());//interface com.breeze.rewrite_mybatis.Table
  42.    
  43.     User2 user2 = new User2();
  44.     Table table2 = user2.getClass().getAnnotation(Table.class);
  45.     System.out.println(table2.value());//sys_user2
  46.     System.out.println(table2.getClass());//class com.sun.proxy.$Proxy1,在本例中,是$Proxy1,但是在其他代码中,执行时,可能有很多动态代理对象,可能时$ProxyN(N是非0的自然数),这里只是表示其是一个代理对象
  47.     System.out.println(table.getClass() == table2.getClass());//true
  48.     System.out.println(table2.annotationType());//interface com.breeze.rewrite_mybatis.Table
  49.    
  50.     System.out.println(table.getClass().getMethod("value").getAnnotation(AliasFor.class) == null);//true
  51.    
  52.     Method valueMethod = Table.class.getMethod("value");
  53.     AliasFor annotation = valueMethod.getAnnotation(AliasFor.class);
  54.     if (annotation != null) {
  55.         System.out.println(annotation.getClass());//class com.sun.proxy.$Proxy2,在本例中,是$Proxy2,但是在其他代码中,执行时,可能有很多动态代理对象,可能时$ProxyN(N是非0的自然数),这里只是表示其是一个代理对象
  56.         System.out.println("AliasFor注解的关联属性:" + annotation.value());//AliasFor注解的关联属性:tableName
  57.     }
  58. }
复制代码
在 Java 中,注解(Annotation,注解在Java中实际上是一种特殊的接口)是通过动态代理机制实现的。当通过反射,获取注解实例时,实际上获取的是一个由 JVM 动态天生的代理对象,而非注解接口本身的实例。
Java 注解(如 @Table)本质上是一个接口,但运行时通过反射获取的注解实例,是一个代理对象(由sun.reflect.annotation.AnnotationInvocationHandler 天生)。
假如要判断 table 是否是 @Table 注解的实例,应使用 Annotation.annotationType() 方法获取注解的真实范例。
总结

一个注解,在JVM运行中,对应一个代理类(com.sun.proxy.$ProxyN,N是非0的自然数),获取到的注解实例,是这个代理类的对象。
这也是,Java语言中,万物皆对象的一个表现,因为注解的本质是接口,接口并不是类,而想创建注解的对象,自然必要创建,一个动态代理类,才华创建对象。因为类才华创建对象,接口是不能的。
这里给出一个说明,在Java的lamda表达式,和函数引用中,看上去,是创建了一个接口的对象,但其本质还是一个匿名内部类的对象。
  1. //在com.breeze.rewrite_mybatis.Main类下
  2. Function<String,String> function = s1 -> s1 + ":" + s1;
  3. Function<String,String> function2 = String::toLowerCase;
  4. System.out.println(function2.getClass());//class com.breeze.rewrite_mybatis.Main$$Lambda$2/1828972342
  5. System.out.println(function.getClass());//class com.breeze.rewrite_mybatis.Main$$Lambda$1/1989780873
复制代码
  1. System.out.println(table.getClass().getMethod("value").getAnnotation(AliasFor.class) == null);//true
复制代码
从上面,这个代码片段,可以看出,注解代理类对象中,并没有织入这个注解(接口)的方法上修饰的注解信息。所以,要获取注解的方法上的注解信息,必须获取到,注解接口的class对象的class对象(注解.class如Table.class,或者使用代理类对象的annotationType()方法获取),而非注解代理类的class对象。
  1.     //在com.breeze.rewrite_mybatis.Main类下   
  2.     Method valueMethod = Table.class.getMethod("value");
  3.     AliasFor annotation = valueMethod.getAnnotation(AliasFor.class);
  4.     if (annotation != null) {
  5.         System.out.println(annotation.getClass());//class com.sun.proxy.$Proxy2,在本例中,是$Proxy2,但是在其他代码中,执行时,可能有很多动态代理对象,可能时$ProxyN(N是非0的自然数),这里只是表示其是一个代理对象
  6.         System.out.println("AliasFor注解的关联属性:" + annotation.value());//AliasFor注解的关联属性:tableName
  7.     }
复制代码
通过雷同,上述代码片段的方式,获取@Table中方法的注解信息和值。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农妇山泉一亩田

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表