如何使自定义注释继承其他注释



我为自定义数据类型创建了一个自定义注释。目前我的实体看起来像这样:

@Entity
public class contact {
@Valid
@Randomizer(EmailAddressValidator.class)
@EmailAddressField
@Convert(converter = EmailAddressConverter.class)
@JsonSerialize(using = EmailAddressSerializer.class)
@Column(name = "email")
private EmailAddress email;
}

但是我想要以下内容

@Entity
public class contact {
@EmailAddressField
@Column(name = "email")
private EmailAddress email;
}

我必须在我自己的注释中做些什么,这样我就不必为每个属性编写其他注释了?

我想把所有的东西都放在一起,只需要为属性写一个注释,为了清晰。

我的注释现在看起来像这样:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE_USE})
@Constraint(
validatedBy = {EmailAddressValidator.class}
)
@Documented
public @interface EmailAddressField {
Class<?>[] groups() default {};
String message() default "No Email Address";
Class<? extends Payload>[] payload() default {};
}

但是如果我把它改成这个,它就不起作用了:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE_USE})
@Constraint(
validatedBy = {EmailAddressValidator.class}
)
@Documented
// -- Annotations from property
@Valid
@Randomizer(EmailAddressValidator.class)
@Convert(converter = EmailAddressConverter.class)
@JsonSerialize(using = EmailAddressSerializer.class)
@Inherited
// --
public @interface EmailAddressField {
Class<?>[] groups() default {};
String message() default "No Email Address";
Class<? extends Payload>[] payload() default {};
}

Java注释是可以应用于方法、类和字段的接口,它们不能有其他注释作为值,因为它们不是对象,它们是一种没有任何方法或状态的元数据形式,它们的主要目的是提供可以被其他工具(如Java编译器或JVM)读取和处理的元数据。

避免编写以下样板代码的一个可能的解决方案是创建一个使用javax.annotation.processing package中的AbstractProcessor class的自定义注释处理器。这将允许您定义自定义注释,并指定在编译期间代码中遇到注释时应该采取的操作。

这是文档;https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/annotation/processing/Processor.htmlhttps://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/annotation/processing/AbstractProcessor.html

在gradle中添加以下依赖项,用于配置@AutoService

dependencies {
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc5'
compileOnly 'com.google.auto.service:auto-service:1.0-rc5'
}

下面是示例代码;

@AutoService(Processor.class)
@SupportedAnnotationTypes("com.example.EmailAddressField")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class EmailAddressFieldProcessor extends AbstractProcessor {
private Elements elementUtils;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
this.elementUtils = processingEnv.getElementUtils();
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement annotation : annotations) {
for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) {
if (element.getKind() == ElementKind.FIELD) {
VariableElement field = (VariableElement) element;
AnnotationMirror validAnnotation = elementUtils.getAnnotationMirror(Valid.class);
field.getAnnotationMirrors().add(validAnnotation);
AnnotationMirror convertAnnotation = elementUtils.getAnnotationMirror(Convert.class);
field.getAnnotationMirrors().add(convertAnnotation);
// BlahBlah.class annotation..... etc...
}
}
}
return true;
}
}