Java的注解

2023-07-30  本文已影响0人  小虎哥的技术博客

一、注解的定义

1.1 通用的注解声明方式

public @interface 注解名 {
    //定义成员
}

1.2 使用元注解定义注解

在定义注解时,必须使用元注解 @Retention、@Target、@Inherited 和 @Documented 说明注解的作用域、使用范围、是否可继承和是否输出到 API 文档中。

@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Target(ElementType.TYPE)
@Documented
public @interface MyAnnotation {
    String name() default "default";
}
1. @Retention

@Retention 注解指定了被修饰的注解保留多长时间。

@Retention 属性取值如下:

2. @Target

@Target 注解指定了注解可以被用来修饰哪些程序元素,例如类、方法、域等。

@Target 的取值类型有以下常量:

3. @Inherited

@Inherited 注解表示标注了此注解的类的子类也会被标注此注解。

4. @Documented

@Documented 注解也被称为文档化注解,加上这个注解后,注解的信息就可以被 javadoc 所解析。

1.3 注解中的成员

注解中的成员可以使用 default 关键字指定默认值。

@Target(ElementType.METHOD)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodInfo {
    String name() default "TestMethod";
    String data() default "2020-05-10";
    int id() default 0;
}

name、data、id 都是注解中的成员变量,在注解使用时都可以使用这些成员变量来对注解进行赋值。

二、使用注解

2.1 注解的解析

可以通过反射机制获取到指定类或方法上的注解信息。

public class RunMyAnnotation {

    @MethodInfo(id=1,name = "Main",data="2022-08-22",value="")
    public void test1(){
        System.out.println("test1");
    }

    public static void main(String[] args) {
        try {
            Method method = RunMyAnnotation.class.getMethod("test1");
            MethodInfo annotation = method.getAnnotation(MethodInfo.class);
            System.out.println("id: " + annotation.id());
            System.out.println("name: " + annotation.name());
            System.out.println("data: " + annotation.data());
            System.out.println("value: " + annotation.value());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

在上面的代码中,使用了反射机制获取到指定类中指定方法的注解信息。

2.2 给注解赋值

注解中成员的赋值,可以使用“成员名=值”的方式进行赋值,如果只有一个成员需要赋值,并且成员名称为"value",那么在赋值时,可以省略成员名称和“=”。

@MethodInfo(name="sayHello")
public void say(){
    System.out.println("Hello Annotation");
}
@MethodInfo("HelloWord!")
public void say(){
    System.out.println("Hello Annotation");
}

2.3 编译时注解处理器

Java 提供了 apt 工具来处理注解,Apt 是 Annotation Processing Tool 的缩写。它是负责在编译期扫描和处理类的注解的程序,也就是提供注释处理器服务的程序。

apt 在 Eclipse 和 IDEA 中的默认设置是关闭的,需要进行配置。

2.4 自定义注解处理器

注解处理器的工作就是扫描源代码中的注解,并解析和使用注解。

自定义注解处理器一般包括两部分:

以 @BindView 注解为例子:

2.4.1 定义注解 @BindView
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
    int value();
}

这个注解用于设置控件的 ID,它只能用于成员变量,作用域是运行时。

2.4.2 自定义注解处理器

自定义注解处理器需要继承 javax.annotation.processing.AbstractProcessor 抽象类并且覆写处理注解的方法。

@SupportedAnnotationTypes("com.yuk.customannotaion.BindView")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MyAnnotationProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        System.out.println("进入注解处理器");

        // 获取到注解@BindView
        Set<? extends Element> es = roundEnvironment.getElementsAnnotatedWith(BindView.class);
        for (Element e : es) {
            // 强转成变量元素
            VariableElement ve = (VariableElement) e;
            // 获取变量元素所在的类
            TypeElement enclosingElement = (TypeElement) ve.getEnclosingElement();
            // 获取类名和包名
            String packageName = elementUtils.getPackageOf(enclosingElement).getQualifiedName().toString();
            String className = enclosingElement.getSimpleName().toString();
            // 控件ID
            int id = ve.getAnnotation(BindView.class).value();
            // 控件名称
            String fieldName = ve.getSimpleName().toString();
            System.out.println(String.format("packageName=%s, className=%s, fieldName=%s, id=%d", packageName, className, fieldName, id));
        }
        System.out.println("退出注解处理器");
        return true;
    }
}

2.5 使用 apt 工具解析注解

在注解处理器完成后,需要通过 apt 工具把注解处理器编译并生成处理结果,并在运行时被解析。

2.5.1 编译注解处理器

使用如下命令编译注解处理器:

javac -encoding UTF-8 MyAnnotationProcessor.java

之后会生成 MyAnnotationProcessor.class 文件。

2.5.2 使用 apt 工具解析注解

使用如下命令编译包含 @BindView 注解的类:

javac -processor com.xxx.xxx.MyAnnotationProcessor TestAnnotation.java

在编译时,Apt 会扫描 @BindView 注解并调用 @BindView 注解处理器生成相应的代码,生成的代码就是把 @BindView 注解的字段和控件ID绑定起来的代码。

上一篇 下一篇

猜你喜欢

热点阅读