J'utilise l'AOP de Guice pour intercepter certains appels de méthode. Ma classe implémente une interface et je voudrais annoter les méthodes d'interface afin que Guice puisse sélectionner les bonnes méthodes. Même si le type d'annotation est annoté avec Inherited , la classe d'implémentation d'annotations n'hérite pas de l'annotation comme indiqué dans Inherited's Java doc:
Notez également que cette méta-annotation entraîne uniquement l'héritage des annotations des superclasses; les annotations sur les interfaces implémentées sont sans effet.
Quelle pourrait en être la raison? Apprendre à connaître toutes les interfaces que la classe d'un objet implémente au runtime n'est pas une chose difficile à faire, il doit donc y avoir une bonne raison derrière cette décision.
Je dirais que la raison en est que sinon un problème d'héritage multiple se poserait.
Exemple:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Inherited
public @interface Baz { String value(); }
public interface Foo{
@Baz("baz") void doStuff();
}
public interface Bar{
@Baz("phleem") void doStuff();
}
public class Flipp{
@Baz("flopp") public void doStuff(){}
}
public class MyClass extends Flipp implements Foo, Bar{}
Si je fais ça:
MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value()
quel sera le résultat? 'baz', 'phleem' ou 'flopp'?
Pour cette raison, les annotations sur les interfaces sont rarement utiles.
Depuis le Javadoc pour @Inherited:
Indique qu'un type d'annotation est automatiquement hérité. Si une méta-annotation Inherited est présente sur une déclaration de type d'annotation et que l'utilisateur interroge le type d'annotation sur une déclaration de classe et que la déclaration de classe n'a pas d'annotation pour ce type, la superclasse de la classe sera automatiquement interrogée pour le type d'annotation. Ce processus sera répété jusqu'à ce qu'une annotation pour ce type soit trouvée ou que le sommet de la hiérarchie de classes (Object) soit atteint. Si aucune super-classe n'a d'annotation pour ce type, la requête indiquera que la classe en question ne possède pas d'annotation de ce type. Notez que ce type de méta-annotation n'a aucun effet si le type annoté est utilisé pour annoter autre chose qu'une classe. Notez également que cette méta-annotation entraîne uniquement l'héritage des annotations des superclasses; les annotations sur les interfaces implémentées sont sans effet.
D'autre part, les validateurs JSR 305 effectuent une sorte de recherche d'héritage. Si vous avez une hiérarchie de classes:
//Person.Java
@Nonnull
public Integer getAge() {...}
//Student.Java (inherits from Person)
@Min(5)
public Integer getAge() {...}
Alors les validations effectives sur Student.getAge()
sont @Nonnull @Min(5)
. @Nonnull
N'a pas de méta-annotation @Inherited
.