自定义注解+反射 实现给注解添加功能的效果

注解我们经常会用到,或者在jdk源码中也会看到,例如: @Deprecated
以及我们在spring或者springboot中经常用到@Controller、@Service、@Repository、@Entity等注解。

是否思考过他们是怎么工作的?

下面我们使用 自定义注解 + 反射给注解加上功能

先贴出整体效果图:
在这里插入图片描述
源码:java8环境

一、定义注解

jdk提供了自定义注解的工具类,在 java.lang.annotation包下

先看下自定义注解的模板:(模板后面有解释)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME) // 注解
@Target({ElementType.FIELD,ElementType.METHOD}) // 定义 @MyAnnotation注解能加在哪些地方,这里表示可以加在字段和方法上
public @interface MyAnnotation {

    String value() default "";

}
第一个注意点是接口需要加上@,也就是@interface

@Retention 可以用来修饰注解,是注解的注解,称为元注解。有下面三种值

1、RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
2、RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
3、RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;最常用

@Target 表示当前注解可以注解在哪些内容上

ElementType枚举值注解作用的范围
FIELD字段上
METHOD方法上
PARAMETER方法的参数上
CONSTRUCTOR构造方法上
PACKAGE包上,参考博客
MODULE模块上 jdk9新增
TYPE类、接口(包括注解类型)、枚举声明、用户自定义的注解
TYPE_USE任意使用类型的地方
TYPE_PARAMETER任何声明类型的地方
LOCAL_VARIABLE本地变量上
ANNOTATION_TYPE元注解上
RECORD_COMPONENTrecord类上jdk14新值

二、实体类上使用注解

加上注解的User对象,暂时注解和对象没有任何关系,只是加上了注解,不要妄想这样注解就能用了,功能部分都要我们自己添加进去,不然鬼知道这个注解到底有什么用途。
如果你想让注解注入属性值、判空等操作,那么我们需要通过反射来处理,后面有使用反射给加上注解的字段赋值

public class User {
    @MyAnnotation(value = "z3")
    private String name;

    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

三、给注解添加功能

通过反射获取字段上的注解,然后获得注解上的值,将注解中的值注入对应字段中

如果要做其它操作,例如判空,赋初值。则得到字段后自己根据需求修改即可。下面只是一个测试案例。

import java.lang.reflect.Field;
import java.util.Optional;

public class MyAnnotationTest {

    public static void main(String[] args) {
        User user = new User(); // 得到一个一个对象
        Field[] fields = user.getClass().getDeclaredFields();// 反射方式得到对象的所有字段
        for (int i = 0; i < fields.length; i++) { // 遍历字段数组
            fields[i].setAccessible(true);  // 将当前字段设置为可访问,不然后面就会报错
            MyAnnotation annotation = fields[i].getAnnotation(MyAnnotation.class); // 获得这个字段的注解
            Optional<MyAnnotation> annotationOptional = Optional.ofNullable(annotation);// 通过java8的Optional容器包裹
            if (!annotationOptional.isEmpty()) {    // 判断注解是否存在,age属性没有添加注解因此需要判空
                String value = annotation.value();  // 得到注解上的值,如果没有值则会是默认的 "" 注解的value方法的default设置
                try {
                    fields[i].set(user, value);     // 给字段赋值
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            fields[i].setAccessible(false);     // 重新将字段设置为不可访问
        }
        System.out.println(user.toString());    // 打印赋值后的user对象
    }

}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页