蕩漾

爱欲之人犹如执炬逆行,必有灼手之患

0%

Java中的注解

注解是干什么的

注解本身不提供作用,注解只能是被看作元数据,它不包含任何业务逻辑。注解更像是一个标签,一个声明,表面被注释的这个地方,将具有某种特定的逻辑。

注解常见的种类

常见的注解有三大类:JDK的,自定义的,第三方的(比如框架)

注解三板斧

定义、使用、读取

定义:包括名字,能用到哪些地方,有效期,是否可以被继承

使用:定义好之后在允许的地方使用标注即可

光有前两步,没什么用,如最熟悉的@Override注解,为什么能验证重写是否有效,怎么不是验证重载?spring的@Autowired为什么是注入作用,而不是输出一句话?显然,他们在程序中做了实现,使得其注解具有各自的作用,也具有了意义,而赋予灵魂的一步就是读取

读取:让注解发挥作用,给注解注入灵魂

注解前置知识

首先是元注解,Java中提供了四个

@Documented | @Retention | @Target | @Inherited

分别解释下

@Documented

代表着此注解会被javadoc工具提取成文档

@Retention:

代表该注解的有效期

SOURCE 表示编译期,如@Override,只做编译时的提示,不会写入字节码中。

CLASS表示类加载期,会保存在class文件中,但在运行class文件被丢弃,也是默认值

RUNTIME 表示运行期,也是最常用的,可以在代码运行时进行反射执行相关的操作

@Target:

表示这个注解可以放在哪

TYPE:接口、类、枚举、注解

FIELD:字段、枚举的常量

METHOD:方法

PARAMETER:参数

CONSTRUCTOR:构造函数

LOCAL_VARIABLE:局部变量

ANNOTATION_TYPE:注解

PACKAGE:包

@Inherited:

表示子类可以继承该类的注解

举个例子
自己自定义个注解,并赋予它作用,模拟aop功能,在方法前后加入

定义注解

1
2
3
4
5
6
7
8
9
10
11
12
//方法前执行
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyBefore {}
//主要方法
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyCore {}
//方法后执行
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAfter {}

使用注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test {
@MyBefore
public void init() {
System.out.println("初始化");
}
@MyAfter
public void destroy() {
System.out.println("销毁");
}
@MyCore
public void core() {
System.out.println("核心方法");
}
}

前两步简单,重要的是如何赋予注解作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class MyWork {
public static void main(String[] args) throws Exception{
//获得测试类
Class clazz = Test.class;
//获得一个实例
Object obj = clazz.newInstance();
//获得Test的所有public方法,将他们存入对应的集合中
List<Method> myBeforeList = new ArrayList<>();
List<Method> myAfterList = new ArrayList<>();
List<Method> myTestList = new ArrayList<>();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(MyBefore.class)) {
myBeforeList.add(method);
continue;
}
if (method.isAnnotationPresent(MyCore.class)) {
myTestList.add(method);
continue;
}
if (method.isAnnotationPresent(MyAfter.class)) {
myAfterList.add(method);
continue;
}
}
//调用标有MyTest注解的方法
for (Method test : myTestList) {
//在测试方法前先执行标有MyBefore注解的方法
for (Method method : myBeforeList) {
method.invoke(obj);
}
//调用test方法
test.invoke(obj);
//在测试方法后执行标有MyAfter注解的方法
for (Method method : myAfterList) {
method.invoke(obj);
}
}
}
}

输出

初始化
核心方法
销毁

-EOF-