自己写一个注解

374 阅读2分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

平时我们开发中最熟悉的就是注解了,新写一个业务类我们需要Controller、service注解,需要添加一个配置,我们需要Configuration、bean注解;以及启动类上的SpringbootApplication注解,以上种种,都体现了注解在我们开发中的身影,那可不可以我们自己也来开发一个注解呢,不为别的,就为开心;

我们知道注解可以用在类上、方法上、属性上,那么程序是如何知道我们的注解该用在什么地方呢,这个就是@Target注解的用处了;在源代码的注释上有这么一段:注释可能出现的语法位置分为声明上下文,其中注释适用于声明,以及类型上下文,其中注释适用于声明和表达式中使用的类型。 常量

ANNOTATION_TYPE(注解类型声明) 、
CONSTRUCTOR(构造函数声明) 、
FIELD(字段声明) 、
LOCAL_VARIABLE (局部变量声明)、
METHOD(方法声明) 、
PACKAGE(包装声明) 、
PARAMETER(形参声明) 、
TYPE(接口、类、枚举、注解)
TYPE_PARAMETER(类型参数声明)对应于 JLS 9.6.4.1 中的声明上下文;

@Retention注解,表示指定要保留多长时间的注释

SOURCE 将为丢弃注解
CLASS 编译器记录在类文件中,但在运行时不需要由 VM 保留。 这是默认行为
RUNTIME 注解会被编译器记录在类文件中,并在运行时由 VM 保留,因此它们可以被反射读取

我们这里为了测试方便用一个method属性

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NameValidator.class)
public @interface MyInnoMain {
}

这里我们需要创建一个类来实现校验

class NameValidator implements  ConstraintValidator<MyInnoMain,Object> {
    private String name;
    @Override
    public void initialize(MyInnoMain constraintAnnotation) {
        System.out.println("------");
        this.name = constraintAnnotation.name();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        System.out.println("------");
        return Test01.valiTest(value);
    }
}

这里需要注意的是@Constraint将注释标记为 Jakarta Bean 验证约束。 给定的约束注释必须由@Constraint注解注释,该注释引用其约束验证实现列表。 每个约束注释必须包含以下属性

String message() default [...]; 它应该默认.message约束的完全限定类名后跟.message的错误消息键。 例如"{com.acme.constraints.NotSafe.message}"
Class<?>[] groups() default {}; 供用户自定义目标群体
Class<? extends Payload>[] payload() default {}; 出于可扩展性的目的

这是官方强制的,我们再写校验方法时需要实现implements ConstraintValidator,至此便可以实现我们的注解了,当我们把它加在某个参数上的时候它便会走到我们的内部逻辑上,看网上有许多利用反射的实现方式,但既然已经有注解替我们实现了,我们还是直接拿来用吧;