J'ai une classe parent Parent
et une classe enfant Child
, définies ainsi:
class Parent {
@MyAnnotation("hello")
void foo() {
// implementation irrelevant
}
}
class Child {
@Override
foo() {
// implementation irrelevant
}
}
Si j'obtiens une référence Method
à Child::foo
, childFoo.getAnnotation(MyAnnotation.class)
me donnera-t-il @MyAnnotation
? Ou sera-ce null
?
Je m'intéresse plus généralement à la façon dont l'annotation fonctionne avec l'héritage Java.
Copié textuellement de http://www.Eclipse.org/aspectj/doc/released/adk15notebook/annotations.html#annotation-inheritance :
Héritage d'annotation
Il est important de comprendre les règles relatives à l'héritage des annotations, car celles-ci ont une incidence sur la correspondance des points de jointure basée sur la présence ou l'absence d'annotations.
Par défaut, les annotations ne sont pas héritées. Étant donné le programme suivant
@MyAnnotation
class Super {
@Oneway public void foo() {}
}
class Sub extends Super {
public void foo() {}
}
Alors
Sub
n'a pas l'annotationMyAnnotation
, etSub.foo()
n'est pas une méthode@Oneway
, Malgré le fait qu'elle écraseSuper.foo()
lequel est.Si un type d'annotation a la méta-annotation
@Inherited
, Alors une annotation de ce type sur une classe entraînera l'héritage de l'annotation par les sous-classes. Ainsi, dans l'exemple ci-dessus, si le typeMyAnnotation
avait l'attribut@Inherited
, AlorsSub
aurait l'annotationMyAnnotation
.Les annotations
@Inherited
Ne sont pas héritées lorsqu'elles sont utilisées pour annoter autre chose qu'un type. Un type qui implémente une ou plusieurs interfaces n'hérite jamais d'annotations des interfaces qu'il implémente.
Vous avez déjà trouvé votre réponse: il n'y a aucune disposition pour l'héritage d'annotation de méthode dans le JDK.
Mais gravir la chaîne des super-classes à la recherche de méthodes annotées est également facile à mettre en œuvre:
/**
* Climbs the super-class chain to find the first method with the given signature which is
* annotated with the given annotation.
*
* @return A method of the requested signature, applicable to all instances of the given
* class, and annotated with the required annotation
* @throws NoSuchMethodException If no method was found that matches this description
*/
public Method getAnnotatedMethod(Class<? extends Annotation> annotation,
Class c, String methodName, Class... parameterTypes)
throws NoSuchMethodException {
Method method = c.getMethod(methodName, parameterTypes);
if (method.isAnnotationPresent(annotation)) {
return method;
}
return getAnnotatedMethod(annotation, c.getSuperclass(), methodName, parameterTypes);
}
En utilisant Spring Core, vous pouvez résoudre avec
Bien que la réponse à la question posée soit que la Method.getAnnotation()
de Java ne considère pas les méthodes substituées, il est parfois utile de trouver ces annotations. Voici une version plus complète de la réponse de Saintali que j'utilise actuellement:
public static <A extends Annotation> A getInheritedAnnotation(
Class<A> annotationClass, AnnotatedElement element)
{
A annotation = element.getAnnotation(annotationClass);
if (annotation == null && element instanceof Method)
annotation = getOverriddenAnnotation(annotationClass, (Method) element);
return annotation;
}
private static <A extends Annotation> A getOverriddenAnnotation(
Class<A> annotationClass, Method method)
{
final Class<?> methodClass = method.getDeclaringClass();
final String name = method.getName();
final Class<?>[] params = method.getParameterTypes();
// prioritize all superclasses over all interfaces
final Class<?> superclass = methodClass.getSuperclass();
if (superclass != null)
{
final A annotation =
getOverriddenAnnotationFrom(annotationClass, superclass, name, params);
if (annotation != null)
return annotation;
}
// depth-first search over interface hierarchy
for (final Class<?> intf : methodClass.getInterfaces())
{
final A annotation =
getOverriddenAnnotationFrom(annotationClass, intf, name, params);
if (annotation != null)
return annotation;
}
return null;
}
private static <A extends Annotation> A getOverriddenAnnotationFrom(
Class<A> annotationClass, Class<?> searchClass, String name, Class<?>[] params)
{
try
{
final Method method = searchClass.getMethod(name, params);
final A annotation = method.getAnnotation(annotationClass);
if (annotation != null)
return annotation;
return getOverriddenAnnotation(annotationClass, method);
}
catch (final NoSuchMethodException e)
{
return null;
}
}