AnnotationUtils.synthesizeAnnotation explicitly checks whether SynthesizedAnnotation is exposable
Issue: SPR-13696
This commit is contained in:
parent
40cff5e340
commit
d0814703c4
|
|
@ -514,7 +514,7 @@ public abstract class AnnotationUtils {
|
|||
try {
|
||||
Annotation[] anns = annotatedElement.getDeclaredAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType().equals(annotationType)) {
|
||||
if (ann.annotationType() == annotationType) {
|
||||
return (A) ann;
|
||||
}
|
||||
}
|
||||
|
|
@ -703,7 +703,7 @@ public abstract class AnnotationUtils {
|
|||
try {
|
||||
Annotation[] anns = clazz.getDeclaredAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType().equals(annotationType)) {
|
||||
if (ann.annotationType() == annotationType) {
|
||||
return (A) ann;
|
||||
}
|
||||
}
|
||||
|
|
@ -828,7 +828,7 @@ public abstract class AnnotationUtils {
|
|||
Assert.notNull(clazz, "Class must not be null");
|
||||
try {
|
||||
for (Annotation ann : clazz.getDeclaredAnnotations()) {
|
||||
if (ann.annotationType().equals(annotationType)) {
|
||||
if (ann.annotationType() == annotationType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1360,7 +1360,8 @@ public abstract class AnnotationUtils {
|
|||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
if (annotation instanceof SynthesizedAnnotation) {
|
||||
if (annotation instanceof SynthesizedAnnotation || (Proxy.isProxyClass(annotation.getClass()) &&
|
||||
Proxy.getInvocationHandler(annotation) instanceof SynthesizedAnnotationInvocationHandler)) {
|
||||
return annotation;
|
||||
}
|
||||
|
||||
|
|
@ -1372,8 +1373,9 @@ public abstract class AnnotationUtils {
|
|||
DefaultAnnotationAttributeExtractor attributeExtractor =
|
||||
new DefaultAnnotationAttributeExtractor(annotation, annotatedElement);
|
||||
InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor);
|
||||
return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(),
|
||||
new Class<?>[] {(Class<A>) annotationType, SynthesizedAnnotation.class}, handler);
|
||||
Class<?>[] exposedInterfaces = (canExposeSynthesizedMarker(annotationType) ?
|
||||
new Class<?>[] {annotationType, SynthesizedAnnotation.class} : new Class<?>[] {annotationType});
|
||||
return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1418,8 +1420,9 @@ public abstract class AnnotationUtils {
|
|||
MapAnnotationAttributeExtractor attributeExtractor =
|
||||
new MapAnnotationAttributeExtractor(attributes, annotationType, annotatedElement);
|
||||
InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor);
|
||||
return (A) Proxy.newProxyInstance(annotationType.getClassLoader(),
|
||||
new Class<?>[] {annotationType, SynthesizedAnnotation.class}, handler);
|
||||
Class<?>[] exposedInterfaces = (canExposeSynthesizedMarker(annotationType) ?
|
||||
new Class<?>[] {annotationType, SynthesizedAnnotation.class} : new Class<?>[] {annotationType});
|
||||
return (A) Proxy.newProxyInstance(annotationType.getClassLoader(), exposedInterfaces, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1539,10 +1542,23 @@ public abstract class AnnotationUtils {
|
|||
}
|
||||
|
||||
attributeAliasesCache.put(annotationType, map);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether we can expose our {@link SynthesizedAnnotation} marker for the given annotation type.
|
||||
* @param annotationType the annotation type that we are about to create a synthesized proxy for
|
||||
*/
|
||||
private static boolean canExposeSynthesizedMarker(Class<? extends Annotation> annotationType) {
|
||||
try {
|
||||
return (Class.forName(SynthesizedAnnotation.class.getName(), false, annotationType.getClassLoader()) ==
|
||||
SynthesizedAnnotation.class);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if annotations of the supplied {@code annotationType} are
|
||||
* <em>synthesizable</em> (i.e., in need of being wrapped in a dynamic
|
||||
|
|
@ -1629,7 +1645,7 @@ public abstract class AnnotationUtils {
|
|||
static String getAttributeOverrideName(Method attribute, Class<? extends Annotation> metaAnnotationType) {
|
||||
Assert.notNull(attribute, "attribute must not be null");
|
||||
Assert.notNull(metaAnnotationType, "metaAnnotationType must not be null");
|
||||
Assert.isTrue(!Annotation.class.equals(metaAnnotationType),
|
||||
Assert.isTrue(Annotation.class != metaAnnotationType,
|
||||
"metaAnnotationType must not be [java.lang.annotation.Annotation]");
|
||||
|
||||
AliasDescriptor descriptor = AliasDescriptor.from(attribute);
|
||||
|
|
@ -1931,7 +1947,7 @@ public abstract class AnnotationUtils {
|
|||
this.sourceAnnotationType = (Class<? extends Annotation>) declaringClass;
|
||||
this.sourceAttributeName = this.sourceAttribute.getName();
|
||||
|
||||
this.aliasedAnnotationType = (Annotation.class.equals(aliasFor.annotation()) ?
|
||||
this.aliasedAnnotationType = (Annotation.class == aliasFor.annotation() ?
|
||||
this.sourceAnnotationType : aliasFor.annotation());
|
||||
this.aliasedAttributeName = getAliasedAttributeName(aliasFor, this.sourceAttribute);
|
||||
try {
|
||||
|
|
@ -1945,7 +1961,7 @@ public abstract class AnnotationUtils {
|
|||
throw new AnnotationConfigurationException(msg, ex);
|
||||
}
|
||||
|
||||
this.isAliasPair = this.sourceAnnotationType.equals(this.aliasedAnnotationType);
|
||||
this.isAliasPair = (this.sourceAnnotationType == this.aliasedAnnotationType);
|
||||
}
|
||||
|
||||
private void validate() {
|
||||
|
|
@ -1979,7 +1995,7 @@ public abstract class AnnotationUtils {
|
|||
|
||||
Class<?> returnType = this.sourceAttribute.getReturnType();
|
||||
Class<?> aliasedReturnType = this.aliasedAttribute.getReturnType();
|
||||
if (!returnType.equals(aliasedReturnType)) {
|
||||
if (returnType != aliasedReturnType) {
|
||||
String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] " +
|
||||
"and attribute [%s] in annotation [%s] must declare the same return type.",
|
||||
this.sourceAttributeName, this.sourceAnnotationType.getName(), this.aliasedAttributeName,
|
||||
|
|
@ -2030,7 +2046,7 @@ public abstract class AnnotationUtils {
|
|||
* @see #isAliasFor
|
||||
*/
|
||||
private boolean isOverrideFor(Class<? extends Annotation> metaAnnotationType) {
|
||||
return this.aliasedAnnotationType.equals(metaAnnotationType);
|
||||
return (this.aliasedAnnotationType == metaAnnotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2087,7 +2103,7 @@ public abstract class AnnotationUtils {
|
|||
|
||||
public String getAttributeOverrideName(Class<? extends Annotation> metaAnnotationType) {
|
||||
Assert.notNull(metaAnnotationType, "metaAnnotationType must not be null");
|
||||
Assert.isTrue(!Annotation.class.equals(metaAnnotationType),
|
||||
Assert.isTrue(Annotation.class != metaAnnotationType,
|
||||
"metaAnnotationType must not be [java.lang.annotation.Annotation]");
|
||||
|
||||
// Search the attribute override hierarchy, starting with the current attribute
|
||||
|
|
|
|||
|
|
@ -23,9 +23,12 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
|
|
@ -632,7 +635,20 @@ public class AnnotatedElementUtilsTests {
|
|||
assertArrayEquals("locations for " + element, EMPTY, contextConfig.locations());
|
||||
// 'value' in @SpringAppConfig should not override 'value' in @ContextConfig
|
||||
assertArrayEquals("value for " + element, EMPTY, contextConfig.value());
|
||||
assertArrayEquals("classes for " + element, new Class<?>[] { Number.class }, contextConfig.classes());
|
||||
assertArrayEquals("classes for " + element, new Class<?>[] {Number.class}, contextConfig.classes());
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -685,7 +701,7 @@ public class AnnotatedElementUtilsTests {
|
|||
// -------------------------------------------------------------------------
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Inherited
|
||||
@interface Transactional {
|
||||
|
||||
|
|
@ -697,7 +713,7 @@ public class AnnotatedElementUtilsTests {
|
|||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Inherited
|
||||
@interface AliasedTransactional {
|
||||
|
||||
|
|
@ -849,7 +865,7 @@ public class AnnotatedElementUtilsTests {
|
|||
String[] value() default {};
|
||||
}
|
||||
|
||||
@ImplicitAliasesContextConfig(xmlFiles = { "A.xml", "B.xml" })
|
||||
@ImplicitAliasesContextConfig(xmlFiles = {"A.xml", "B.xml"})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface ComposedImplicitAliasesContextConfig {
|
||||
}
|
||||
|
|
@ -938,7 +954,7 @@ public class AnnotatedElementUtilsTests {
|
|||
String pattern();
|
||||
}
|
||||
|
||||
@ComponentScan(excludeFilters = { @Filter(pattern = "*Test"), @Filter(pattern = "*Tests") })
|
||||
@ComponentScan(excludeFilters = {@Filter(pattern = "*Test"), @Filter(pattern = "*Tests")})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface TestComponentScan {
|
||||
|
||||
|
|
@ -1037,7 +1053,7 @@ public class AnnotatedElementUtilsTests {
|
|||
}
|
||||
}
|
||||
|
||||
public static interface GenericParameter<T> {
|
||||
public interface GenericParameter<T> {
|
||||
|
||||
T getFor(Class<T> cls);
|
||||
}
|
||||
|
|
@ -1057,23 +1073,23 @@ public class AnnotatedElementUtilsTests {
|
|||
}
|
||||
|
||||
@Transactional
|
||||
public static interface InheritedAnnotationInterface {
|
||||
public interface InheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
public static interface SubInheritedAnnotationInterface extends InheritedAnnotationInterface {
|
||||
public interface SubInheritedAnnotationInterface extends InheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
public static interface SubSubInheritedAnnotationInterface extends SubInheritedAnnotationInterface {
|
||||
public interface SubSubInheritedAnnotationInterface extends SubInheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
@Order
|
||||
public static interface NonInheritedAnnotationInterface {
|
||||
public interface NonInheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
public static interface SubNonInheritedAnnotationInterface extends NonInheritedAnnotationInterface {
|
||||
public interface SubNonInheritedAnnotationInterface extends NonInheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
public static interface SubSubNonInheritedAnnotationInterface extends SubNonInheritedAnnotationInterface {
|
||||
public interface SubSubNonInheritedAnnotationInterface extends SubNonInheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
@ConventionBasedComposedContextConfig(locations = "explicitDeclaration")
|
||||
|
|
@ -1144,4 +1160,8 @@ public class AnnotatedElementUtilsTests {
|
|||
static class SpringAppConfigClass {
|
||||
}
|
||||
|
||||
@Resource(name = "x")
|
||||
static class ResourceHolder {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue