注解与反射实战

2023-09-21 注解反射

首先定义一个枚举类,当然这不是必须要,主要是尽可能涵盖注解可使用的类型。

public enum RequestMethod {
    GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
    private RequestMethod() {}
}

# 定义两个注解

RequestMapping注解要求只能作用在类和方法上,如果利用反射则必须要保证运行时可见。

@Target({ElementType.TYPE, ElementType.METHOD}) // 可以作用在类和方法上
@Retention(RetentionPolicy.RUNTIME) // 必须保证运行时仍然有效不然会被丢弃
public @interface RequestMapping {

    String url(); // 没有默认值代表url必填

    RequestMethod[] method() default {}; // 有默认值可不填
}

定义Value注解,只能作用在字段上。

@Target({ElementType.FIELD}) //只能作用在字段上
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {

    String value();
}

# 创建使用注解的测试类

类上定义一个@RequestMapping注解,然后定义两个成员变量一个加@Value一个不加。

@RequestMapping(url = "/test", method = RequestMethod.GET)
public class TestController {

    @Value("www.xk857.com")
    private String name;

    private String age;

    public String getName() {
        return name;
    }

    public String getAge() {
        return age;
    }
}

# Main方法通过反射实现注解功能

  1. 获取类RequestMapping注解中的信息
  2. 给有@Value注解的字段设置值为注解中的值
public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException {
        Class<?> clazz = Class.forName("demo.annotation.TestController");

        // 获取该类上所有注解
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            // 如果是RequestMapping则打印url值
            if (annotation.annotationType().equals(RequestMapping.class)) {
                RequestMapping requestMapping = (RequestMapping) annotation;
                System.out.println("请求路径为:" + requestMapping.url());
            }
        }

        TestController testController = new TestController();
        // 获取所有字段,并判断字段是否有注解@Value,如果有则设置值
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            // 如果该字段有@Value注解,则设置值
            if (field.isAnnotationPresent(Value.class)) {
                Value value = field.getAnnotation(Value.class);
                field.setAccessible(true);
                field.set(testController, value.value());
            }
        }
        System.out.println("名称=" + testController.getName());
        System.out.println("年龄=" + testController.getAge());
    }
}

# 总结

代码 含义
clazz.getAnnotations() 获取该类上的所有注解,不包含方法和成员变量的注解
getAnnotation(注解.class) 获取该 类/字段/方法 某个注解上的内容
isAnnotationPresent(注解.class) 判断该 类/字段/方法 是否有某个注解
上次更新: 5 个月前