自定义注解

自定义注解常见的格式如下:

@Target(ElementType.Method)
@Retention(Retention.Runtime)
@Documented
@Inherited

public @interface LoginAnnotation{
 ModuleType module();
 int age() default 18;
 String object() default ""; 

}

分析如下:

一、4个注解的作用:

-----@Target:用来表示自定义注解可以运用在哪些元素上面,以JAVA自带的ElementType的枚举类型进行定义,其中里面包括了如下10种作用位置:

TYPE(类、接口或者枚举的声明)、 FIELD(属性的声明)、 METHOD(方法的声明)、PARAMETER(方法形式参数声明)、CONSTRUCTOR(构造方法的声明)、LOCAL_VARIABLE(局部变量的声明)、ANNOTATION_TYPE(注解类型的声明)、PACKAGE(包的声明)、TYPE_PARAMETER(参数类型的声明)、TYPE_USE(使用类型的声明)

 

-----@Retention:表示自定义作用于代码的哪个生命周期,以JAVA自带的RetentionPolicy的枚举类型进行定义,包括3个阶段:

SOURCE:不会参与编译也不会参与运行,相当于注释。

CLASS:在编译器运行的时候会进行处理,但是我们在运行JVM的时候会忽略,也就是运行期读取不到。默认情况是采用这个注解,但是实际开发中几乎都需要采用RUNTIME。

RUNTIME:会参与运行,也就是说在程序运行阶段,我们可以通过反射得到这个注解,并通过判断是否有这个注解或者这个注解中属性的值,从而执行不同的程序代码。

 

------@Documented:指定自定义注解是否能随着被定义的java文件生成到JavaDoc文档当中。

------@Inherited:指定某个自定义注解如果写在了父类的声明部分,那么子类的声明部分也能自动拥有该注解。

二、代码分析:

和接口、枚举类似,自定义注解也有关键字:@interface

再看方法中的代码:

1)代码的修饰符默认为public,可以不写

2)default表示默认值,值的话需要和定义的类型一致。

 

将自定义注解注入到相关代码上,紧接着就需要通过反射技术获取到注解。

1、结合spring的AOP技术进行使用,参考代码。

注:下面代码自定义注解的作用范围是方法,如果配置在属性上,就要从该属性对应的Field对象上去获取;如果是配置在类上,就要去从Class对象上获取。

@Component
@Aspect
public class LogAspect() {

# 定义切点
# 因为是和注解相关的,因此表达式为@annotation(自定义注解全路径)
@Pointcut("@annotation(com.cn.example.LogAnnotation)")
private void doLog() {
}

@Around("doLog()")
public Object doSystemLog(ProceedingJoinPoint point) {
 #得到当前连接点的签名
 # 默认返回Signature,但是其不提供getMethod(),需要转换成MethodSignature,该类
 # 继承了Signature类
 MethodSignature methodSignature=(MethodSignature)point.getSignature();
 #获取方法
 Method  method=methodSignature.getMethod();
 #获取所有参数信息
 Object[] arguments=method.getArgs();
 # 获取我们自己自定义的注解
 LogAnnotation annotation=method.getAnnotation(LogAnnotation.class);
 

}
}

  

 参考链接:https://www.cnblogs.com/qiumingcheng/p/5923928.html

 

此外,比如在实体类的属性注入自定义注解,代码如下

public class PmsBrandVo {

    @ApiModelProperty(value = "品牌名称", required = true)
    @NotNull(message = "品牌名称不能为空")
    @NotBlank(message = "品牌名称不能为空")
    private String name;

    @ApiModelProperty(value = "品牌首字母", required = true)
    private String firstLetter;

    @ApiModelProperty(value = "排序")
    @Min(value = 0)
    private Integer sort;

    @ApiModelProperty(value = "是否为品牌制造商:0->不是;1->是")
    @FlagValidation(values = {"0", "1"}, message = "制造商状态格式不正确")
    private Integer factoryStatus;
}

  其中@FlagValidation为我们自己设置的自定义注解,代码如下:

//作用在接口/类/注解、属性声明上
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// 这个注解引入真正做验证的类,也就是FlagValidationClass @Constraint(validatedBy = FlagValidationClass.class) public @interface FlagValidation { String[] values() default {}; String message(); //下面这个2个必须加,否则会报错 Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; }

  

public class FlagValidationClass implements ConstraintValidator<FlagValidation, Integer> {
    private String[] values;

    @Override
    public void initialize(FlagValidation flagValidation) {
        this.values = flagValidation.values();
    }

    @Override
    public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
        boolean isFlag = false;
        for (int i = 0; i < values.length; i++) {
            if (values[i].equals(String.valueOf(integer))) {
                isFlag = true;
                break;
            }
        }
        return isFlag;
    }
}

  

posted @ 2020-09-07 14:43  曾饺  阅读(2636)  评论(0编辑  收藏  举报