java 优雅之道--注解
基础知识:
在注解之前,XML 是各大框架的 青睐者,主要是以松耦合的方式完成了框架中几乎所有的配置,随着项目越来越大,xml维护越来越复杂。
有人提出来一种标记式高耦合的配置方式--注解,可以在方法上,属性上,类上 。。。 几乎所有需要配置的地方都可以进行注解。
java 注解来源于反射技术,注解的本质就是一个继承了 Annotation 接口的接口。
具体实现在 java.lang.reflect.ReflectAccess 中,该类实现了 LangReflectAccess 接口
使用 javadoc 来查询一个类的注解: 利用 javadoc -d 生成的目录 类.java Doclet 自动代码生成
如何生成:通过AnnotationTypeDoc,ClassDoc,FieldDocAnnotationValue[] 等这些接口找到注解,然后生成了接口文档。
java的注释(5.0)和javadoc里最早的注解关联在一起的。
一个注解准确的来说只不过是一个特殊的注释,如果没有解析他的代码,甚至连注释都不如。
解析一个类或方法的注解有两种方式:
1 编译期直接扫描 编译器在对java字节码编译过程中会检测到某个类或者方法被注解修饰,就对这些注解进行分析处理。
典型的就是 @Override 会自动去父类检查是否有相同的方法。
2 运行期反射
注解需要注意的地方:
注解是一个接口,接口里只有常量和我们的虚拟方法,所以说注解里没有实际变量,只有虚拟变量。使得JVM能够同interface的编译,解析,调用方式保持一致。
注解的节点中只能有 String , class 和 enums 这三种类型
Annotation 是一个modifiers,如 public,static or final或者 arrays 才能使用。
如果注解只有一个element的话, 那么建议为 String value() 来去标明(类型随意). 如 @interface Test{String value()} 使用时候 @Test("这里是value的值")
如果注解里没有任何 Element 的话,那么就是一个 Mark (标识) 类型的注解
原生注解类型: @Retention(RetentionPolicy.RUNTIME) 用在什么地方(运行时)
@target(ElementType.METHOD) 用在什么地方(方法类型上)
注解的本身结构:
注解里的element节点都是什么类型:
1: a primtive type 原始类型
2:String
3:Class or invocation class class或被调用的class
4: An enum type
5: An annocation type 注解类型
6: An array type: Array类型
元注解: -- 用于修饰注解的注解
@target 说明了Annotation 所修饰的对象范围: Annotation 可被用于 Packages,type(类,接口,枚举,Annotation类型),
类型成员(方法,构造方法,成员变量,枚举值),方法参数和本地变量(如循环变量,catch参数)
比如 SpringMVC 的 @controller 就是用在了 ElementType.TYPE,如果用在多个方面可以再添加 @target(ElementType.TYPE,ElementType.FIELD)
如:
@retention 用在哪个时刻,RetentionPolicy.SOURCE 源代码,注解将被编译期丢弃
RetentionPolicy.CLASS compare 编译期级别,注解将被记录在class中,但是VM运行时不会保留
RetentionPolicy.RUNTIME 注解记录在class中,同时在vm中被保留,可以通过反射方法获取到。
如 @TestAnnotation 获取方法为 Main m = Main.class; TestAnnotation ta = m.getAnnotation(TestAnnotaion.class);
@Document 被 @Document 标记的注解将会在生成 javadoc 时被包含在javadoc中,注解默认在生成javadoc中不会包含。
@Inherited 允许被子类继承的注解,注解默认不允许被继承,单在使用 Inherited 后子类可以继承父类的注解。
一般在类上配置,然后子类可以继承后仍然拥有注解。
java 内置三大注解:
@Override 标记式注解,仅被编译器可知,判断是否通过编译。
@Deprecated 表示不被推荐使用
@SupperessWarnings 压制java警告
注解的底层原理: 编译为字节码之后的存在形式
Class 类中提供了以下一些方法用于反射注解。
-
-
-
getAnnotation:返回指定的注解
-
isAnnotationPresent:判定当前元素是否被指定注解修饰
-
getAnnotations:返回所有的注解
-
getDeclaredAnnotation:返回本元素的指定注解
-
getDeclaredAnnotations:返回本元素的所有注解,不包含父类继承而来的
-
-
Annotation 用到极致的地方 就是 SpringBoot 入口是 EnnableAutoConfiguration 注解