Spring 注解原理
一、背景
1、Annotation:
提供了一种为程序元素设置元数据的方法,可用于修饰包、类、构造器、方法、成员变量、参数和局部变量(具体详见元注解 Target)的声明。
注解可以被一些解析工具或者是编译工具进行解析。
Annotation中的信息可以在编译、加载和运行时被读取(具体详见元注解 Retention),并执行相应的处理。
2、Metadata:
中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。
指从信息资源中抽取出来的用于说明其特征、内容的结构化的数据(如题名、版本、出版数据、相关说明、检索点等),用于组织、描述、检索、保存、管理信息和知识资源。
任何文件系统中的数据都分为数据和元数据。数据是指普通文件中的实际数据,而元数据指用来描述一个文件的特征的系统数据,诸如访问权限、文件拥有者以及文件数据块的分布信息(inode…)等等。在集群文件系统中,分布信息包括文件在磁盘上的位置以及磁盘在集群中的位置。用户需要操作一个文件必须首先得到它的元数据,才能定位到文件的位置并且得到文件的内容或相关属性。
HTML的head里有一个meta标签。meta的属性有两种(name、http-equiv),name属性用来描述网页的内容,http-equiv属性指示服务器在发送实际的文档之前先在要传送给浏览器的 MIME 文档头部包含名称/值对,比如用以说明主页制作所使用的文字以及语言。
3、XML:
XML被广泛的应用于描述元数据。
4、XML vs Annotation:
- xml 作为可扩展标记语言最大的优势在于开发者能够为软件量身【定制】适用的标记,使代码更加通俗易懂。
- 利用 xml 配置能使软件更具扩展性。例如 Spring 将 class 间的依赖配置在 xml 中,最大限度地提升应用的可扩展性。
- 具有成熟的验证机制确保程序正确性。利用 Schema 或 DTD 可以对 xml 的正确性进行验证,避免了非法的配置导致应用程序出错。
- 修改配置而无需变动现有程序。
- 需要解析工具或类库的支持。
- 解析 xml 势必会影响应用程序性能,占用系统资源。
- 配置文件过多导致管理变得困难。
- 编译期无法对其配置项的正确性进行验证,或要查错只能在运行期。
- IDE 无法验证配置项的正确性。
- 查错变得困难,往往配置的一个手误导致莫名其妙的错误。
- 开发人员不得不同时维护代码和配置文件,开发效率变得低下。
- 配置项与代码间存在潜规则。改变了任何一方都有可能影响另外一方。
- 保存在 class 文件中,降低维护成本。
- 无需工具支持,无需解析。
- 编译期即可验证正确性,查错变得容易。
- 提升开发效率。
- 若要对配置项进行修改,不得不修改 Java 文件,重新编译打包应用。
- 配置项编码在 Java 文件中,可扩展性差。
二、注解
1、@interface:定义一个Annotation类型的接口,可以包含成员变量。
- Annotation的成员变量以无形参的方法形式来声明,其方法名和返回值定义了该成员变量的名字和类型。
- 使用带有属性的Annotation时,必须为其属性指定值,否则会报错。
- 定义Annotation时可以使用【default】关键字为属性设置默认值。
- 如果Annotation中具有名为【value】的属性,在使用时如果只使用value属性的话,可以不写属性名直接指定值。
- Annotation的属性类型只能是基本类型、String、enum、Class及上述类型的一维数组类型。
- 对于数组类型,当数组中只有一个元素时,可以省略大括号。
2、meta-annotation:
四个原注解(@Target、@Retention、@Documented、@Inherited),注解其他注解。
Java5.0定义了4个标准的 meta-annotation 类型,它们被用来提供对其它 annotation 类型作说明(只能作用在注解上,不能作用在其他程序元素上)。
2.1、@Target:元素种类,指示注解类型所适用的程序元素的种类。由 ElementType 限定。
- ElementType.TYPE:注解到接口、类、枚举、注解上
- ElementType.FIELD:注解到属性字段、枚举的常量上
- ElementType.METHOD:注解到方法上
- ElementType.PARAMETER:注解到方法参数上
- ElementType.CONSTRUCTOR:注解到构造方法上
- ElementType.LOCAL_VARIABLE:注解到局部变量上
- ElementType.ANNOTATION_TYPE:注解到注解类型元素的声明上(表明为原注解)
- ElementType.PACKAGE:注解到包上
- ElementType.TYPE_PARAMETER:注解到@since 1.8上
- ElementType.TYPE_USE:注解到@since 1.8上
2.2、@Retention:保留策略【重要】
指示注解类型的注解要保留多久。如果注解类型声明中不存在 Retention 注解,则保留策略默认为 RetentionPolicy.CLASS。
-
- RetentionPolicy.SOURCE:注解保留在源代码中,但是编译的时候会被编译器所丢弃。
- RetentionPolicy.CLASS:默认,注解会被保留在class文件中,但是在运行时期间就不会识别这个注解。
- RetentionPolicy.RUNTIME:注解会被保留在class文件中,同时运行时期间也会被识别。所以可以使用反射机制获取注解信息。
- RetentionPolicy.SOURCE:注解保留在源代码中,但是编译的时候会被编译器所丢弃。
2.3、@Documented:文档化
指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化。
一个类型的声明是用 @Documented 来注解的,则其注解将成为注解元素的公共 API 的一部分。
2.4、@Inherited:自动继承
说明子类可以继承父类中的该注解。
指示注解类型被自动继承。如果在注解类型声明中存在 Inherited 元注解,并且用户在某一类声明中查询该注解类型,同时该类声明中没有此类型的注解,则将在该类的超类中自动查询该注解类型。此过程会重复进行,直到找到此类型的注解或到达了该类层次结构的顶层 (Object) 为止。如果没有超类具有该类型的注解,则查询将指示当前类没有这样的注解。
sda