总体解释
注解介绍
- 那如何去解析注解呢?用到Java强大的反射功能。
反射-可以通过类对象获取到这个类的各种信息比如成员变量、方法等,
那注解标记能不能通过反射获取呢?能。
所以注解的原理其实很简单,本质上是通过反射功能动态获取注解标记,然后按照不同的注解执行不同的操作,比如@Autowired可以注入一个对象给变量赋值。
注解结构体
- 一个注解可以简单拆解为三个部分:
第一部分:注解体
注解的定义有点类似于接口(interface),只不过前面一个加了一个@符号,这个千万不能省。
第二部分:注解变量
注解变量的语法有点类似于接口里面定义的方法,变量名后面带一对括号,不同的是注解变量后面可以有默认值。另外返回值只能是Java基本类型、String类型或者枚举类,不可以是对象类型。
第三部分:元注解
元注解(meta-annotation)说白了就是给注解加注解的注解,是不是有点晕了,这种注解是JDK提前内置好的,可以直接拿来用的。不太懂也没有关系反正数量也不多,总共就4个,我们背下来吧:@Target @Retention @Documented @Inherited
Target注解
用来描述注解的使用范围,即被修饰的注解可以用在什么地方 。
注解可以用于修饰 packages、types(类、接口、枚举、注解类)、类成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数),在定义注解类时使用了@Target 能够更加清晰的知道它能够被用来修饰哪些对象,具体的取值范围定义在ElementType.java 枚举类中。
比如上面我们写的Redis锁的注解就只能用于方法上了。
Retention注解
用来描述注解保留的时间范围,即注解的生命周期。在 RetentionPolicy 枚举类中定义了三个周期:
public enum RetentionPolicy {
SOURCE, // 源文件保留
CLASS, // 编译期保留,默认值
RUNTIME // 运行期保留,可通过反射去获取注解信息
}
像我们熟知的@Override注解就只能保留在源文件中,代码编译后注解就消失了。比如上面我们写的Redis锁的注解就保留到了运行期,运行的时候可以通过反射获取信息。
Documented注解
用来描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息,很简单不多解释了。
Inherited注解
被Inherited注解修饰的注解具有继承性,如果父类使用了被@Inherited修饰的注解,则其子类将自动继承该注解。
相关业务
-
定义的注解(@EnableRedisLock)中没有业务逻辑,只有一些变量,别忘了我们的注解是要使能Redis分布式锁的功能,那这个注解到底是怎么实现加锁和释放锁的功能呢?这个就需要我们借助反射的强大功能了。
-
这里借助了切面的功能,将EnableRedisLock注解作为一个切点,只要方法上标注了这个注解就会自动执行这里的代码逻辑。
通过反射机制拿到注解对象后就可以执行加锁解锁的常用逻辑啦。