Affects: spring-core 5.2.1
When updating from 5.1.10 to 5.2.0 / 5.2.1, then AnnotationUtils.findAnnotation(Class<?> clazz, @Nullable Class<A> annotationType)
no longer finds annotations that are created on the parent.
Example project https://github.com/sellersj/spring-annotationutils-issue
I thought that https://github.com/spring-projects/spring-framework/issues/23856 was the same issue, but updating to 5.2.1 didn't fix the issue.
Comment From: sbrannen
Thanks for raising the issue.
I have confirmed that this is a regression; however, the scope is slightly more limited than your initial claim.
Specifically, the regression only applies to annotations that are not declared as @Inherited
and whose package name starts with java.
-- for example @java.lang.Deprecated
, as in your demo project.
To illustrate this, the following modified version of your test class passes against master
(i.e., 5.2.x
).
package com.example;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import org.junit.Test;
import org.springframework.core.annotation.AnnotationUtils;
import static org.junit.Assert.assertTrue;
public class AnnotationTest {
@Test
public void isClassDeprecated_DirectlyOnclass() {
assertTrue("should mark as deprecated", isClassDeprecated(DeprecatedClass.class));
}
@Test
public void isClassDeprecated_OnAbstractclass() {
assertTrue("should mark as deprecated", isClassDeprecated(DeprecatedAbstractClass.class));
}
@Test
public void isClassDeprecated_OnSuperclass() {
assertTrue("should mark as deprecated", isClassDeprecated(SubClass.class));
}
private static boolean isClassDeprecated(Class<?> clazz) {
return null != AnnotationUtils.findAnnotation(clazz, MyDeprecated.class);
}
@MyDeprecated
static class DeprecatedClass {
}
@MyDeprecated
abstract static class DeprecatedAbstractClass {
}
static class SubClass extends SuperClass {
}
@MyDeprecated
static class SuperClass {
}
@Retention(RetentionPolicy.RUNTIME)
// @Inherited
@interface MyDeprecated {
}
}
I have changed the title of this issue accordingly.
Comment From: jhoeller
Generally speaking, those AnnotationUtils
operations are not meant to bend the standard Java annotation semantics, they are rather meant to operate on Spring-style annotations. Also, it constitutes an important performance optimization in 5.2 to bypass MergedAnnotations
lookups for plain java.lang
annotations completely. Our new internal metamodel there doesn't even store java.lang
annotations so also saves some memory for cached class hierarchy representations.
That said, point taken that this worked before, in particular for the @Deprecated
use case. I've restored basic superclass traversal for findAnnotation(Class, ...)
even for the plain annotation case.