基础理论
注解的定义—@interface
@interface 用来定义一个自定义注解
在Java中,定义注解其实和定义接口差多不,只需要在interface前添加一个@符号就可以,即 @interface Zhujie{ },这就表明我们定义了一个名为 @Zhujie 的注解。
注解中的方法即为注解的元素,元素中不能包含参数,返回值只能为简单数据类型、String、Class、emnus、注释 和这些类型的数组
//自定义注解 @Zhujie ,该注解有两个元素 personId、company
public @interface Zhujie(){
int personId(); //元素1
String company() default "[unassigned]"; //元素2
}
注解定义完之后就可以使用了,注解是一种特殊的修饰符,在其他修饰符(例如,public、static 或者 final 等)使用地方都可以使用注解。
按照惯例,注解应该放在其他修饰符的前面。
注解的声明用@符号后面跟上这个注解类型的名字,再后面加上括号,括号中列出这个注释中元素的key-value对,其中,元素名为key ,值必须是常量。例如:
@Zhujie(personId=20151120,company="YeePay")
如果注解中只有一个元素且元素名字为 value,那么在使用这个注解的时候,元素的名字和等号都可以省略,例如:
public @interface Zhujie(){
String value();
}
//使用方式
@Zhujie(value="hello")
或
@Zhujie("hello")
注解 和 xml
以前XML是各大框架的青睐者,它以松耦合的方式完成了框架中几乎所有的配置,但是随着项目越来越庞大,XML的内容也越来越复杂,维护成本变高。于是就有人提出来一种标记式高耦合的配置方式——注解。
方法上可以进行注解,类上也可以注解,字段属性上也可以注解,反正几乎需要配置的地方都可以进行注解。关于注解和XML两种不同的配置模式,争论了好多年了,各有各的优劣,
注解可以提供更大的便捷性,易于维护修改,但耦合度高,而XML相对于注解则是相反的。追求低耦合就要抛弃高效率,追求效率必然会遇到耦合。
注解的本质
refer to : https://www.cnblogs.com/zyrblog/p/9946009.html
所有的注解类型都继承自Annotation这个普通的接口。我们看一个 JDK 内置注解的定义:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
这是注解 @Override 的定义,本质上就是:
public interface Override extends Annotation{
}
注解的本质就是一个继承了 Annotation 接口的接口。
一个注解准确意义上来说,只不过是一种特殊的注释而已,如果没有解析它的代码,它可能连注释都不如。
而解析一个类或者方法的注解往往有两种形式,一种是编译期直接的扫描,一种是运行期反射。
编译期直接的扫描
编译器的扫描指的是编译器在对 java 代码编译字节码的过程中会检测到某个类或者方法被一些注解修饰,这时它就会对于这些注解进行某些处理。
典型的就是注解 @Override,一旦编译器检测到某个方法被修饰了 @Override 注解,编译器就会检查当前方法的方法签名是否真正重写了父类的某个方法,也就是比较父类中是否具有一个同样的方法签名。这一种情况只适用于那些编译器已经熟知的注解类,比如 JDK 内置的几个注解。
而自定义的注解,编译器是不知道这个注解的作用的,当然也不知道该如何处理,往往只是会根据该注解的作用范围来选择是否编译进字节码文件,仅此而已。
没有元素的注解称为标记注解。元注解是用于修饰注解的注解,通常用在注解的定义上,如上面的 @Override 注解的定义,可以看到其中的 @Target,@Retention 两个注解就是我们所谓的元注解,元注解一般用于指定某个注解生命周期以及作用目标等信息。
运行期反射
通过反射,获取到类或者方法上,添加了哪些注解,并且获得这些注解方法 和 对应的值。
拿到这些信息后,我们再基于这些信息,做一些数据处理。比如spring中的bean创建、aop代理等等,都是使用@Component注解、@Aspect注解等。
也就是说,注解只是一种标记,他本身不做任何逻辑处理,也没有调用栈。
我们需要额外,提供一个,用了解析注解的代码,在解析代码中,才基于注解标记,以及设置的值,做一些逻辑处理。
注解带来的问题
注解,虽然好像比xml的耦合性更高了点,但还是会,导致逻辑的零碎。一个逻辑,被拆成了多个部分,每个部分,只有其中一小部分的逻辑,然后,多个部分,通过注解,来进行连接。
如果想知道完整逻辑,必须把 每个部分,都读懂,必须基于注解,来做各个部分的衔接嵌套。
总体上,给人感觉逻辑零碎。。。