自定义注解
自定义注解常见的格式如下:
@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;
}
}

浙公网安备 33010602011771号