-
Notifications
You must be signed in to change notification settings - Fork 38.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make AnnotationsUtils.findAnnotation()
recognize annotations on anonymous classes again
#28896
Make AnnotationsUtils.findAnnotation()
recognize annotations on anonymous classes again
#28896
Conversation
…ous classes again Closes spring-projectsgh-28895
AnnotationsUtils.findAnnotation()
Hi @janeisklar, I ran the following example application against Spring Framework 6.0.x, 5.3.x, 5.2.x, 5.1.x, and 5.0.0, and it fails every time. For Spring 6.0.x, I ran against JDK 17.0.8+9-LTS-211. For the Spring 5.x variants, I ran against JDK 1.8.0_362-b09. package example;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
public class TestMain {
public static void main(String[] args) {
Object object = new @TypeUseAnnotation Object() {};
Class<?> clazz = object.getClass();
TypeUseAnnotation annotation = AnnotationUtils.findAnnotation(clazz, TypeUseAnnotation.class);
Assert.state(annotation != null, "annotation is null");
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeUseAnnotation {
}
} Are you certain that your tests passed on Spring Framework 5.x and JDK 8? If so, which exact versions of Spring and the JDK did you test against? In the interim, I am closing this PR in favor of #31360. Unless I'm mistaken, Spring Framework has never provided explicit/intentional support for finding Though, if you can provide a working example to prove otherwise, please do. Thanks, Sam |
AnnotationsUtils.findAnnotation()
TYPE_USE
annotations in the MergedAnnotations
infrastructure
TYPE_USE
annotations in the MergedAnnotations
infrastructureAnnotationsUtils.findAnnotation()
recognize annotations on anonymous classes again
Hi @sbrannen, I did not notice that before, but it seems to be important that you add The following test passes on my system: $ java -version
openjdk version "1.8.0_382"
OpenJDK Runtime Environment (build 1.8.0_382-8u382-ga-1~22.04.1-b05)
OpenJDK 64-Bit Server VM (build 25.382-b05, mixed mode) package com.foo;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Test;
import org.springframework.core.annotation.AnnotationUtils;
class ReproducerTest {
@Test
void findsAnnotationOnAnnotatedObject() {
final Object a = new @TypeAnnotation Object() {};
assertNotNull(AnnotationUtils.findAnnotation(a.getClass(), TypeAnnotation.class));
}
@Test
void doesNotFindAnnotationOnAnnotatedObject() {
final Object a = new @TypeUseAnnotation Object() {};
TypeUseAnnotation annotation = AnnotationUtils.findAnnotation(a.getClass(), TypeUseAnnotation.class);
assertNull(annotation);
}
@Target({ ElementType.TYPE, ElementType.TYPE_USE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface TypeAnnotation {}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeUseAnnotation {}
} <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>type-use-bug-reproducer</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.13</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.7.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project> Thank you for looking into this! Best, |
Thanks for the feedback, @janeisklar.
That was the missing piece of the puzzle. After further investigation, I've determined that your use case was never intended to work. Spring uses
There were apparently changes made in Java 12 that fixed the bug that your code relied on (though, I was not able to locate the specific issue for that change). Consequently, your test passes on Java 8-11 but fails with Java 12+. Furthermore, all of the traditional methods that Spring has been using for years (like
Similarly, methods such as
In light of that, I have changed the label for this issue to |
Thank you for the insights, @sbrannen. In case it helps: I have been using this It's not a feature that one's life depends on, but it can be quite handy. |
You're welcome!
Ahhh, OK. Thanks for providing the use case. FWIW, if that's your goal, you can achieve the same via a "local class" instead of an "anonymous class" as follows. class AnnotatedLocalClassTests {
@Test
void test() {
@TypeUseAnnotation
class AnnotatedObject extends Object /* or some bean/component type */ {
};
Object object = new AnnotatedObject();
Class<?> clazz = object.getClass();
TypeUseAnnotation annotation = AnnotationUtils.findAnnotation(clazz, TypeUseAnnotation.class);
assertThat(annotation).isNotNull();
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeUseAnnotation {
}
} |
Overview
In Spring 5,
AnnotationUtils.findAnnotation(Class<?>, Class<A>)
would find the annotation on the following class:Object foo = new @MyAnnotation Object() {};
-- for example,AnnotationUtils.findAnnotation(foo, MyAnnotation.class)
would not return null.With Spring 6.0.0-M5 / Java 17 the annotation will no longer be found.
See gh-28895