Restore javax meta-annotation lookup behavior

Closes gh-22957
This commit is contained in:
Juergen Hoeller 2019-06-11 20:56:41 +02:00
parent fd159ad082
commit b37390b8fe
3 changed files with 64 additions and 6 deletions

View File

@ -80,6 +80,7 @@ dependencies {
optional("io.netty:netty-buffer") optional("io.netty:netty-buffer")
testCompile("io.projectreactor:reactor-test") testCompile("io.projectreactor:reactor-test")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}") 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("org.xmlunit:xmlunit-matchers:2.6.2")
testCompile("javax.xml.bind:jaxb-api:2.3.1") testCompile("javax.xml.bind:jaxb-api:2.3.1")
testCompile("com.fasterxml.woodstox:woodstox-core:5.2.0") { testCompile("com.fasterxml.woodstox:woodstox-core:5.2.0") {

View File

@ -956,7 +956,7 @@ public abstract class AnnotationUtils {
return false; return false;
} }
String name = clazz.getName(); String name = clazz.getName();
return (name.startsWith("java") || name.startsWith("org.springframework.lang.")); return (name.startsWith("java.") || name.startsWith("org.springframework.lang."));
} }
/** /**

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,6 +17,7 @@
package org.springframework.core.annotation; package org.springframework.core.annotation;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited; import java.lang.annotation.Inherited;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -28,7 +29,10 @@ import java.lang.reflect.Method;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.annotation.meta.When;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Rule; import org.junit.Rule;
@ -36,6 +40,7 @@ import org.junit.Test;
import org.junit.internal.ArrayComparisonFailure; import org.junit.internal.ArrayComparisonFailure;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.springframework.lang.NonNullApi;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.stereotype.Indexed; import org.springframework.stereotype.Indexed;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -118,6 +123,14 @@ public class AnnotatedElementUtilsTests {
assertFalse(hasMetaAnnotationTypes(ComposedTransactionalComponentClass.class, ComposedTransactionalComponent.class.getName())); 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 @Test
public void isAnnotatedOnNonAnnotatedClass() { public void isAnnotatedOnNonAnnotatedClass() {
assertFalse(isAnnotated(NonAnnotatedClass.class, TX_NAME)); assertFalse(isAnnotated(NonAnnotatedClass.class, TX_NAME));
@ -147,6 +160,14 @@ public class AnnotatedElementUtilsTests {
assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, ComposedTransactionalComponent.class.getName())); 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 @Test
public void getAllAnnotationAttributesOnNonAnnotatedClass() { public void getAllAnnotationAttributesOnNonAnnotatedClass() {
assertNull(getAllAnnotationAttributes(NonAnnotatedClass.class, TX_NAME)); assertNull(getAllAnnotationAttributes(NonAnnotatedClass.class, TX_NAME));
@ -207,6 +228,22 @@ public class AnnotatedElementUtilsTests {
attributes.get("value")); attributes.get("value"));
} }
@Test
public void getAllAnnotationAttributesOnLangType() {
MultiValueMap<String, Object> attributes = getAllAnnotationAttributes(
NonNullApi.class, Nonnull.class.getName());
assertNotNull(attributes);
assertEquals(asList(When.ALWAYS), attributes.get("when"));
}
@Test
public void getAllAnnotationAttributesOnJavaxType() {
MultiValueMap<String, Object> attributes = getAllAnnotationAttributes(
ParametersAreNonnullByDefault.class, Nonnull.class.getName());
assertNotNull(attributes);
assertEquals(asList(When.ALWAYS), attributes.get("when"));
}
@Test @Test
public void getMergedAnnotationAttributesOnClassWithLocalAnnotation() { public void getMergedAnnotationAttributesOnClassWithLocalAnnotation() {
Class<?> element = TxConfig.class; Class<?> element = TxConfig.class;
@ -701,14 +738,33 @@ public class AnnotatedElementUtilsTests {
@Test @Test
public void javaLangAnnotationTypeViaFindMergedAnnotation() throws Exception { public void javaLangAnnotationTypeViaFindMergedAnnotation() throws Exception {
Constructor<?> deprecatedCtor = Date.class.getConstructor(String.class); Constructor<?> deprecatedCtor = Date.class.getConstructor(String.class);
assertEquals(deprecatedCtor.getAnnotation(Deprecated.class), findMergedAnnotation(deprecatedCtor, Deprecated.class)); assertEquals(deprecatedCtor.getAnnotation(Deprecated.class),
assertEquals(Date.class.getAnnotation(Deprecated.class), findMergedAnnotation(Date.class, Deprecated.class)); findMergedAnnotation(deprecatedCtor, Deprecated.class));
assertEquals(Date.class.getAnnotation(Deprecated.class),
findMergedAnnotation(Date.class, Deprecated.class));
} }
@Test @Test
public void javaxAnnotationTypeViaFindMergedAnnotation() throws Exception { public void javaxAnnotationTypeViaFindMergedAnnotation() throws Exception {
assertEquals(ResourceHolder.class.getAnnotation(Resource.class), findMergedAnnotation(ResourceHolder.class, Resource.class)); assertEquals(ResourceHolder.class.getAnnotation(Resource.class),
assertEquals(SpringAppConfigClass.class.getAnnotation(Resource.class), findMergedAnnotation(SpringAppConfigClass.class, 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 @Test
@ -1288,6 +1344,7 @@ public class AnnotatedElementUtilsTests {
} }
@Resource(name = "x") @Resource(name = "x")
@ParametersAreNonnullByDefault
static class ResourceHolder { static class ResourceHolder {
} }