web-dev-qa-db-fra.com

Comment étendre les annotations Java?

Dans mon projet, j'utilise une annotation prédéfinie @With:

@With(Secure.class)
public class Test { //....

Le code source de @With:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface With { 

    Class<?>[] value() default {};
}

Je veux écrire l'annotation personnalisée @Secure, qui aura le même effet que @With(Secure.class). Comment faire ça?


Et si je fais comme ça? Est-ce que ça marchera?

@With(Secure.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Secure {

}
23
bvitaliyg

D'après la spécification du langage Java, Chapitre 9.6 Types d'annotation :

Aucune clause de prolongation n'est autorisée. (Les types d'annotation étendent implicitement annotation.Annotation.) 

Donc, vous ne pouvez pas étendre une annotation. vous devez utiliser un autre mécanisme ou créer un code qui reconnaît et traite votre propre annotation. Spring vous permet de regrouper les autres annotations de Spring dans vos propres annotations personnalisées. mais toujours, pas d'extension.

15
piotrek

Comme l'a souligné piotrek, vous ne pouvez pas étendre les annotations au sens d'héritage. Néanmoins, vous pouvez créer des annotations qui agrègent les autres:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SuperAnnotation {
    String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SubAnnotation {
    SuperAnnotation superAnnotation();
    String subValue();
}

Usage:

@SubAnnotation(subValue = "...", superAnnotation = @SuperAnnotation(value = "superValue"))
class someClass { ... }
15
Halmackenreuter
@With(Secure.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Secure {

}

Cela fonctionnera.

5

Vous pouvez utiliser une annotation pour une annotation comme ceci:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@WithSecurityContext(factory = WithCustomUserSecurityContextFactory.class)
public @interface WithCustomUser {
  String username() default "[email protected]";
  String password() default "demo";
  String[] authorities() default {Authority.USER};
}

Et définir l'état exact dans son "enfant"

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@WithCustomUser(username = "[email protected]",
                password = "admin",
                authorities = {Authority.USER, Authority.ADMINISTRATOR})
public @interface WithAdminUser {
}

Dans ce cas, vous avez un certain "état" et un accès aux champs d'annotation parent via réflexion/aspect.

0
user2210419