ps:由于时间有限来不及看太详细,所以只写个大概,后面有机会会进行详细补全。
疑问的起点以前在写代码的时候就看过一些注解的源码,每次点进去看的时候发现都只有简简单单几行代码,但是为什么就可以实现一些非常复杂的功能呢?哪个时候还不太在意,今天在写代码的时候,看到了@Slf4j的注解,突然想看看它的源码是什么,然后点进去一看
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package lombok.extern.slf4j;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
public @interface Slf4j {
String topic() default "";
}
这就是所有的代码,还是一如既往的简单,再去看了其他的注解依然如此,那么究竟靠什么来实现对应的功能呢?
注解如何起作用 注解与接口注解实际上就是一个标签,我们在一个某一类事物打标签的时候也是尽量越简单越好,所以注解就是这么回事,它仅仅是一个标签,其代码结构如下:
public @interface 注解名称{
属性列表
;
}
仅仅是注解名字加上注解的一些属性,然后我们又注意到,它的定义方式是
@interface
interface我们都知道,是一个接口,那么猜测注解的本质上类似接口,所以注解才会如此简单,因为接口也是如此仅仅定义方法而不去实现,想到这一层之后脑子里突然明朗起来。
为什么都说注解实际上就是使用反射实现的,我们已经看过了注解里面的东西,就这么一点,与反射有什么关系呢?但是大家都说注解就是用反射实现的自然有其的道理。
如果自己使用过一些反射代码,就会留意到有这么一个方法:
xxx.getAnnotation(annotation.class)
xxx代表着一个对象,annotation.class代表一个注解的class,我们可以通过这个方法来获取一个类上相应的注解。
还可以直接判断一个对象上是否使用了某某注解:
xxx.isAnnotationPresent(annotation.class)
至此我们应该已经想到了一个注解对应的功能是如何实现的了。
- 当我们注明一个注解的时候,只是制造出了一个标签当我们给一个类加上注解的时候,就是给这个对象贴上了某个标签然后实现一个方法:通过反射得到一个对象,然后判断对象上是否有此注解,如果有再进行相应的操作,通过反射我们可以得到这个对象的所有信息,所以想要进行什么操作也是可以的。
这就是注解从定义到起作用的一个过程,举个第三步的例子:
当我们给一个方法加上了一个注解
public class TestAnnotation {
public static void main(String[] args) {
XXX类 对象= new XXX();
Class clazz = 对象.getClass();
Method[] method = clazz.getDeclaredMethods();
for ( Method m: method ) {
if ( m.isAnnotationPresent( annotation.class )) {
如果方法有此注解,我们就可以进行想要进行的操作
...........
}
}
}
至此我们对注解的实现应该有了一个初步的了解了,以下是注解的其他基本概念。
注解基本概念元注解是负责对其它注解进行说明的注解,自定义注解时可以使用元注解。Java 5 定义了 4 个注解,分别是 @documented、@Target、@Retention 和 @Inherited。Java 8 又增加了 @Repeatable 和 @Native 两个注解。
@documented@documented 是一个标记注解,没有成员变量。用 @documented 注解修饰的注解类会被 Javadoc 工具提取成文档。默认情况下,Javadoc 是不包括注解的,但如果声明注解时指定了 @documented,就会被 Javadoc 之类的工具处理,所以注解类型信息就会被包括在生成的帮助文档中。
@Target@Target 注解用来指定一个注解的使用范围,即被 @Target 修饰的注解可以用在什么地方。@Target 注解有一个成员变量(value)用来设置适用目标,value 是 java.lang.annotation.ElementType 枚举类型的数组,下表为 ElementType 常用的枚举常量。
ElementType.ANNOTATION_TYPE 可以给一个注解进行注解ElementType.ConSTRUCTOR 可以给构造方法进行注解ElementType.FIELD 可以给属性进行注解ElementType.LOCAL_VARIABLE 可以给局部变量进行注解ElementType.METHOD 可以给方法进行注解ElementType.PACKAGE 可以给一个包进行注解ElementType.PARAMETER 可以给一个方法内的参数进行注解ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举 @Retention
@Retention 用于描述注解的生命周期,也就是该注解被保留的时间长短。@Retention 注解中的成员变量(value)用来设置保留策略,value 是 java.lang.annotation.RetentionPolicy 枚举类型,RetentionPolicy 有 3 个枚举常量,如下所示。保留时长后面的包含前面的。
- SOURCE:在源文件中有效(即源文件保留)CLASS:在 class 文件中有效(即 class 保留)RUNTIME:在运行时有效(即运行时保留)
@Inherited 是一个标记注解,用来指定该注解可以被继承。使用 @Inherited 注解的 Class 类,表示这个注解可以被用于该 Class 类的子类。就是说如果某个类使用了被 @Inherited 修饰的注解,则其子类将自动具有该注解。
@Repeatable@Repeatable 注解是 Java 8 新增加的,它允许在相同的程序元素中重复注解,在需要对同一种注解多次使用时,往往需要借助 @Repeatable 注解。Java 8 版本以前,同一个程序元素前最多只能有一个相同类型的注解,如果需要在同一个元素前使用多个相同类型的注解,则必须使用注解“容器”。重复使用赋予不同的值,相当于全都放到集合之中。
@Native使用 @Native 注解修饰成员变量,则表示这个变量可以被本地代码引用,常常被代码生成工具使用。
由于才疏学浅,难免有错漏之处,还望不吝赐教。
本文地址转载请注明:https://blog.csdn.net/elapse_/article/details/122645746
Java元注解作用及使用:http://c.biancheng.net/view/7009.html
秒懂,Java 注解 (Annotation)你可以这样学:https://zhuanlan.zhihu.com/p/27643133



