From b37390b8fedc722e8f152123b92e1ad5fc7c34f7 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 11 Jun 2019 20:56:41 +0200 Subject: [PATCH] Restore javax meta-annotation lookup behavior Closes gh-22957 --- spring-core/spring-core.gradle | 1 + .../core/annotation/AnnotationUtils.java | 2 +- .../AnnotatedElementUtilsTests.java | 67 +++++++++++++++++-- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/spring-core/spring-core.gradle b/spring-core/spring-core.gradle index 685f18de2f..bda90aad82 100644 --- a/spring-core/spring-core.gradle +++ b/spring-core/spring-core.gradle @@ -80,6 +80,7 @@ dependencies { optional("io.netty:netty-buffer") testCompile("io.projectreactor:reactor-test") testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}") + testCompile("com.google.code.findbugs:jsr305:3.0.2") testCompile("org.xmlunit:xmlunit-matchers:2.6.2") testCompile("javax.xml.bind:jaxb-api:2.3.1") testCompile("com.fasterxml.woodstox:woodstox-core:5.2.0") { diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index 8a54477466..2280729ec0 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -956,7 +956,7 @@ public abstract class AnnotationUtils { return false; } String name = clazz.getName(); - return (name.startsWith("java") || name.startsWith("org.springframework.lang.")); + return (name.startsWith("java.") || name.startsWith("org.springframework.lang.")); } /** diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java index 80f6a133c6..eb1298f52d 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.springframework.core.annotation; import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; @@ -28,7 +29,10 @@ import java.lang.reflect.Method; import java.util.Date; import java.util.List; import java.util.Set; +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.Resource; +import javax.annotation.meta.When; import org.junit.Ignore; import org.junit.Rule; @@ -36,6 +40,7 @@ import org.junit.Test; import org.junit.internal.ArrayComparisonFailure; import org.junit.rules.ExpectedException; +import org.springframework.lang.NonNullApi; import org.springframework.stereotype.Component; import org.springframework.stereotype.Indexed; import org.springframework.util.Assert; @@ -118,6 +123,14 @@ public class AnnotatedElementUtilsTests { assertFalse(hasMetaAnnotationTypes(ComposedTransactionalComponentClass.class, ComposedTransactionalComponent.class.getName())); } + @Test + public void isAnnotatedForPlainTypes() { + assertTrue(isAnnotated(Order.class, Documented.class)); + assertTrue(isAnnotated(NonNullApi.class, Documented.class)); + assertTrue(isAnnotated(NonNullApi.class, Nonnull.class)); + assertTrue(isAnnotated(ParametersAreNonnullByDefault.class, Nonnull.class)); + } + @Test public void isAnnotatedOnNonAnnotatedClass() { assertFalse(isAnnotated(NonAnnotatedClass.class, TX_NAME)); @@ -147,6 +160,14 @@ public class AnnotatedElementUtilsTests { assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, ComposedTransactionalComponent.class.getName())); } + @Test + public void hasAnnotationForPlainTypes() { + assertTrue(hasAnnotation(Order.class, Documented.class)); + assertTrue(hasAnnotation(NonNullApi.class, Documented.class)); + assertTrue(hasAnnotation(NonNullApi.class, Nonnull.class)); + assertTrue(hasAnnotation(ParametersAreNonnullByDefault.class, Nonnull.class)); + } + @Test public void getAllAnnotationAttributesOnNonAnnotatedClass() { assertNull(getAllAnnotationAttributes(NonAnnotatedClass.class, TX_NAME)); @@ -207,6 +228,22 @@ public class AnnotatedElementUtilsTests { attributes.get("value")); } + @Test + public void getAllAnnotationAttributesOnLangType() { + MultiValueMap attributes = getAllAnnotationAttributes( + NonNullApi.class, Nonnull.class.getName()); + assertNotNull(attributes); + assertEquals(asList(When.ALWAYS), attributes.get("when")); + } + + @Test + public void getAllAnnotationAttributesOnJavaxType() { + MultiValueMap attributes = getAllAnnotationAttributes( + ParametersAreNonnullByDefault.class, Nonnull.class.getName()); + assertNotNull(attributes); + assertEquals(asList(When.ALWAYS), attributes.get("when")); + } + @Test public void getMergedAnnotationAttributesOnClassWithLocalAnnotation() { Class element = TxConfig.class; @@ -701,14 +738,33 @@ public class AnnotatedElementUtilsTests { @Test public void javaLangAnnotationTypeViaFindMergedAnnotation() throws Exception { Constructor deprecatedCtor = Date.class.getConstructor(String.class); - assertEquals(deprecatedCtor.getAnnotation(Deprecated.class), findMergedAnnotation(deprecatedCtor, Deprecated.class)); - assertEquals(Date.class.getAnnotation(Deprecated.class), findMergedAnnotation(Date.class, Deprecated.class)); + assertEquals(deprecatedCtor.getAnnotation(Deprecated.class), + findMergedAnnotation(deprecatedCtor, Deprecated.class)); + assertEquals(Date.class.getAnnotation(Deprecated.class), + findMergedAnnotation(Date.class, Deprecated.class)); } @Test public void javaxAnnotationTypeViaFindMergedAnnotation() throws Exception { - assertEquals(ResourceHolder.class.getAnnotation(Resource.class), findMergedAnnotation(ResourceHolder.class, Resource.class)); - assertEquals(SpringAppConfigClass.class.getAnnotation(Resource.class), findMergedAnnotation(SpringAppConfigClass.class, Resource.class)); + assertEquals(ResourceHolder.class.getAnnotation(Resource.class), + findMergedAnnotation(ResourceHolder.class, Resource.class)); + assertEquals(SpringAppConfigClass.class.getAnnotation(Resource.class), + findMergedAnnotation(SpringAppConfigClass.class, Resource.class)); + } + + @Test + public void javaxMetaAnnotationTypeViaFindMergedAnnotation() throws Exception { + assertEquals(ParametersAreNonnullByDefault.class.getAnnotation(Nonnull.class), + findMergedAnnotation(ParametersAreNonnullByDefault.class, Nonnull.class)); + assertEquals(ParametersAreNonnullByDefault.class.getAnnotation(Nonnull.class), + findMergedAnnotation(ResourceHolder.class, Nonnull.class)); + } + + @Test + public void nullableAnnotationTypeViaFindMergedAnnotation() throws Exception { + Method method = TransactionalServiceImpl.class.getMethod("doIt"); + assertEquals(method.getAnnotation(Resource.class), findMergedAnnotation(method, Resource.class)); + assertEquals(method.getAnnotation(Resource.class), findMergedAnnotation(method, Resource.class)); } @Test @@ -1288,6 +1344,7 @@ public class AnnotatedElementUtilsTests { } @Resource(name = "x") + @ParametersAreNonnullByDefault static class ResourceHolder { } -- GitLab