注解
工作原理
- package com.breeze.rewrite_mybatis;
- import java.lang.annotation.*;
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD})
- public @interface AliasFor {
- @AliasFor("attribute")
- String value() default "";
- @AliasFor("value")
- String attribute() default "";
- }
- package com.breeze.rewrite_mybatis;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- public @interface Table {
- @AliasFor("value")
- String tableName() default "";
- @AliasFor("tableName")
- String value();//value不能为空
- }
- package com.breeze.rewrite_mybatis;
- @Table("sys_user")
- public class User {
- ...
- }
- package com.breeze.rewrite_mybatis;
- @Table("sys_user2")
- public class User2 {
- ...
- }
- //在com.breeze.rewrite_mybatis.Main类下
- public static void main(String[] args){
- User user1 = new User();
- Table table = user1.getClass().getAnnotation(Table.class);
- System.out.println(table.value());//sys_user
- System.out.println(Table.class);//interface com.breeze.rewrite_mybatis.Table
- System.out.println(table.getClass());//class com.sun.proxy.$Proxy1
- System.out.println(table.annotationType());//interface com.breeze.rewrite_mybatis.Table
-
- User2 user2 = new User2();
- Table table2 = user2.getClass().getAnnotation(Table.class);
- System.out.println(table2.value());//sys_user2
- System.out.println(table2.getClass());//class com.sun.proxy.$Proxy1,在本例中,是$Proxy1,但是在其他代码中,执行时,可能有很多动态代理对象,可能时$ProxyN(N是非0的自然数),这里只是表示其是一个代理对象
- System.out.println(table.getClass() == table2.getClass());//true
- System.out.println(table2.annotationType());//interface com.breeze.rewrite_mybatis.Table
-
- System.out.println(table.getClass().getMethod("value").getAnnotation(AliasFor.class) == null);//true
-
- Method valueMethod = Table.class.getMethod("value");
- AliasFor annotation = valueMethod.getAnnotation(AliasFor.class);
- if (annotation != null) {
- System.out.println(annotation.getClass());//class com.sun.proxy.$Proxy2,在本例中,是$Proxy2,但是在其他代码中,执行时,可能有很多动态代理对象,可能时$ProxyN(N是非0的自然数),这里只是表示其是一个代理对象
- System.out.println("AliasFor注解的关联属性:" + annotation.value());//AliasFor注解的关联属性:tableName
- }
- }
复制代码 在 Java 中,注解(Annotation,注解在Java中实际上是一种特殊的接口)是通过动态代理机制实现的。当通过反射,获取注解实例时,实际上获取的是一个由 JVM 动态天生的代理对象,而非注解接口本身的实例。
Java 注解(如 @Table)本质上是一个接口,但运行时通过反射获取的注解实例,是一个代理对象(由sun.reflect.annotation.AnnotationInvocationHandler 天生)。
假如要判断 table 是否是 @Table 注解的实例,应使用 Annotation.annotationType() 方法获取注解的真实范例。
总结
一个注解,在JVM运行中,对应一个代理类(com.sun.proxy.$ProxyN,N是非0的自然数),获取到的注解实例,是这个代理类的对象。
这也是,Java语言中,万物皆对象的一个表现,因为注解的本质是接口,接口并不是类,而想创建注解的对象,自然必要创建,一个动态代理类,才华创建对象。因为类才华创建对象,接口是不能的。
这里给出一个说明,在Java的lamda表达式,和函数引用中,看上去,是创建了一个接口的对象,但其本质还是一个匿名内部类的对象。- //在com.breeze.rewrite_mybatis.Main类下
- Function<String,String> function = s1 -> s1 + ":" + s1;
- Function<String,String> function2 = String::toLowerCase;
- System.out.println(function2.getClass());//class com.breeze.rewrite_mybatis.Main$$Lambda$2/1828972342
- System.out.println(function.getClass());//class com.breeze.rewrite_mybatis.Main$$Lambda$1/1989780873
复制代码- System.out.println(table.getClass().getMethod("value").getAnnotation(AliasFor.class) == null);//true
复制代码 从上面,这个代码片段,可以看出,注解代理类对象中,并没有织入这个注解(接口)的方法上修饰的注解信息。所以,要获取注解的方法上的注解信息,必须获取到,注解接口的class对象的class对象(注解.class如Table.class,或者使用代理类对象的annotationType()方法获取),而非注解代理类的class对象。- //在com.breeze.rewrite_mybatis.Main类下
- Method valueMethod = Table.class.getMethod("value");
- AliasFor annotation = valueMethod.getAnnotation(AliasFor.class);
- if (annotation != null) {
- System.out.println(annotation.getClass());//class com.sun.proxy.$Proxy2,在本例中,是$Proxy2,但是在其他代码中,执行时,可能有很多动态代理对象,可能时$ProxyN(N是非0的自然数),这里只是表示其是一个代理对象
- System.out.println("AliasFor注解的关联属性:" + annotation.value());//AliasFor注解的关联属性:tableName
- }
复制代码 通过雷同,上述代码片段的方式,获取@Table中方法的注解信息和值。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |