Merge branch '3.2.x'
* 3.2.x: (28 commits) Hide 'doc' changes from jdiff reports Document @Bean 'lite' mode vs @Configuration Final preparations for 3.2.2 Remove Tiles 3 configuration method Polishing Extracted buildRequestAttributes template method from FrameworkServlet Added "beforeExistingAdvisors" flag to AbstractAdvisingBeanPostProcessor Minor refinements along the way of researching static CGLIB callbacks Compare Kind references before checking log levels Polish Javadoc in RequestAttributes Fix copy-n-paste errors in NativeWebRequest Fix issue with restoring included attributes Add additional test for daylight savings glitch Document context hierarchy support in the TCF Fix test for daylight savings glitch Make the methodParameter field of HandlerMethod final Disable AsyncTests in spring-test-mvc Reformat the testing chapter Document context hierarchy support in the TCF Document context hierarchy support in the TCF ...
This commit is contained in:
@@ -20,6 +20,7 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
@@ -240,14 +241,58 @@ public abstract class AnnotationUtils {
|
||||
* if not found
|
||||
* @see Class#isAnnotationPresent(Class)
|
||||
* @see Class#getDeclaredAnnotations()
|
||||
* @see #findAnnotationDeclaringClassForTypes(List, Class)
|
||||
* @see #isAnnotationDeclaredLocally(Class, Class)
|
||||
*/
|
||||
public static Class<?> findAnnotationDeclaringClass(Class<? extends Annotation> annotationType, Class<?> clazz) {
|
||||
Assert.notNull(annotationType, "Annotation type must not be null");
|
||||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
return (isAnnotationDeclaredLocally(annotationType, clazz)) ? clazz :
|
||||
findAnnotationDeclaringClass(annotationType, clazz.getSuperclass());
|
||||
return (isAnnotationDeclaredLocally(annotationType, clazz)) ? clazz : findAnnotationDeclaringClass(
|
||||
annotationType, clazz.getSuperclass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first {@link Class} in the inheritance hierarchy of the specified
|
||||
* {@code clazz} (including the specified {@code clazz} itself) which declares
|
||||
* at least one of the specified {@code annotationTypes}, or {@code null} if
|
||||
* none of the specified annotation types could be found.
|
||||
* <p>If the supplied {@code clazz} is {@code null}, {@code null} will be
|
||||
* returned.
|
||||
* <p>If the supplied {@code clazz} is an interface, only the interface itself
|
||||
* will be checked; the inheritance hierarchy for interfaces will not be traversed.
|
||||
* <p>The standard {@link Class} API does not provide a mechanism for determining
|
||||
* which class in an inheritance hierarchy actually declares one of several
|
||||
* candidate {@linkplain Annotation annotations}, so we need to handle this
|
||||
* explicitly.
|
||||
* @param annotationTypes the list of Class objects corresponding to the
|
||||
* annotation types
|
||||
* @param clazz the Class object corresponding to the class on which to check
|
||||
* for the annotations, or {@code null}
|
||||
* @return the first {@link Class} in the inheritance hierarchy of the specified
|
||||
* {@code clazz} which declares an annotation of at least one of the specified
|
||||
* {@code annotationTypes}, or {@code null} if not found
|
||||
* @see Class#isAnnotationPresent(Class)
|
||||
* @see Class#getDeclaredAnnotations()
|
||||
* @see #findAnnotationDeclaringClass(Class, Class)
|
||||
* @see #isAnnotationDeclaredLocally(Class, Class)
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public static Class<?> findAnnotationDeclaringClassForTypes(List<Class<? extends Annotation>> annotationTypes,
|
||||
Class<?> clazz) {
|
||||
Assert.notEmpty(annotationTypes, "The list of annotation types must not be empty");
|
||||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Class<? extends Annotation> annotationType : annotationTypes) {
|
||||
if (isAnnotationDeclaredLocally(annotationType, clazz)) {
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
return findAnnotationDeclaringClassForTypes(annotationTypes, clazz.getSuperclass());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,8 +393,8 @@ public abstract class AnnotationUtils {
|
||||
* and corresponding attribute values as values
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public static AnnotationAttributes getAnnotationAttributes(
|
||||
Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
|
||||
public static AnnotationAttributes getAnnotationAttributes(Annotation annotation, boolean classValuesAsString,
|
||||
boolean nestedAnnotationsAsMap) {
|
||||
|
||||
AnnotationAttributes attrs = new AnnotationAttributes();
|
||||
Method[] methods = annotation.annotationType().getDeclaredMethods();
|
||||
@@ -371,15 +416,15 @@ public abstract class AnnotationUtils {
|
||||
}
|
||||
}
|
||||
if (nestedAnnotationsAsMap && value instanceof Annotation) {
|
||||
attrs.put(method.getName(), getAnnotationAttributes(
|
||||
(Annotation)value, classValuesAsString, nestedAnnotationsAsMap));
|
||||
attrs.put(method.getName(),
|
||||
getAnnotationAttributes((Annotation) value, classValuesAsString, nestedAnnotationsAsMap));
|
||||
}
|
||||
else if (nestedAnnotationsAsMap && value instanceof Annotation[]) {
|
||||
Annotation[] realAnnotations = (Annotation[])value;
|
||||
Annotation[] realAnnotations = (Annotation[]) value;
|
||||
AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length];
|
||||
for (int i = 0; i < realAnnotations.length; i++) {
|
||||
mappedAnnotations[i] = getAnnotationAttributes(
|
||||
realAnnotations[i], classValuesAsString, nestedAnnotationsAsMap);
|
||||
mappedAnnotations[i] = getAnnotationAttributes(realAnnotations[i], classValuesAsString,
|
||||
nestedAnnotationsAsMap);
|
||||
}
|
||||
attrs.put(method.getName(), mappedAnnotations);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -16,21 +16,26 @@
|
||||
|
||||
package org.springframework.core.annotation;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.core.annotation.AnnotationUtils.*;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import static org.springframework.core.annotation.AnnotationUtils.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AnnotationUtils}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
@@ -102,23 +107,91 @@ public class AnnotationUtilsTests {
|
||||
assertNull(findAnnotationDeclaringClass(Transactional.class, NonAnnotatedClass.class));
|
||||
|
||||
// inherited class-level annotation; note: @Transactional is inherited
|
||||
assertEquals(InheritedAnnotationInterface.class, findAnnotationDeclaringClass(Transactional.class,
|
||||
InheritedAnnotationInterface.class));
|
||||
assertEquals(InheritedAnnotationInterface.class,
|
||||
findAnnotationDeclaringClass(Transactional.class, InheritedAnnotationInterface.class));
|
||||
assertNull(findAnnotationDeclaringClass(Transactional.class, SubInheritedAnnotationInterface.class));
|
||||
assertEquals(InheritedAnnotationClass.class, findAnnotationDeclaringClass(Transactional.class,
|
||||
InheritedAnnotationClass.class));
|
||||
assertEquals(InheritedAnnotationClass.class, findAnnotationDeclaringClass(Transactional.class,
|
||||
SubInheritedAnnotationClass.class));
|
||||
assertEquals(InheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClass(Transactional.class, InheritedAnnotationClass.class));
|
||||
assertEquals(InheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClass(Transactional.class, SubInheritedAnnotationClass.class));
|
||||
|
||||
// non-inherited class-level annotation; note: @Order is not inherited,
|
||||
// but findAnnotationDeclaringClass() should still find it.
|
||||
assertEquals(NonInheritedAnnotationInterface.class, findAnnotationDeclaringClass(Order.class,
|
||||
NonInheritedAnnotationInterface.class));
|
||||
// but findAnnotationDeclaringClass() should still find it on classes.
|
||||
assertEquals(NonInheritedAnnotationInterface.class,
|
||||
findAnnotationDeclaringClass(Order.class, NonInheritedAnnotationInterface.class));
|
||||
assertNull(findAnnotationDeclaringClass(Order.class, SubNonInheritedAnnotationInterface.class));
|
||||
assertEquals(NonInheritedAnnotationClass.class, findAnnotationDeclaringClass(Order.class,
|
||||
NonInheritedAnnotationClass.class));
|
||||
assertEquals(NonInheritedAnnotationClass.class, findAnnotationDeclaringClass(Order.class,
|
||||
SubNonInheritedAnnotationClass.class));
|
||||
assertEquals(NonInheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClass(Order.class, NonInheritedAnnotationClass.class));
|
||||
assertEquals(NonInheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClass(Order.class, SubNonInheritedAnnotationClass.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAnnotationDeclaringClassForTypesWithSingleCandidateType() {
|
||||
|
||||
// no class-level annotation
|
||||
List<Class<? extends Annotation>> transactionalCandidateList = Arrays.<Class<? extends Annotation>> asList(Transactional.class);
|
||||
assertNull(findAnnotationDeclaringClassForTypes(transactionalCandidateList, NonAnnotatedInterface.class));
|
||||
assertNull(findAnnotationDeclaringClassForTypes(transactionalCandidateList, NonAnnotatedClass.class));
|
||||
|
||||
// inherited class-level annotation; note: @Transactional is inherited
|
||||
assertEquals(InheritedAnnotationInterface.class,
|
||||
findAnnotationDeclaringClassForTypes(transactionalCandidateList, InheritedAnnotationInterface.class));
|
||||
assertNull(findAnnotationDeclaringClassForTypes(transactionalCandidateList,
|
||||
SubInheritedAnnotationInterface.class));
|
||||
assertEquals(InheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClassForTypes(transactionalCandidateList, InheritedAnnotationClass.class));
|
||||
assertEquals(InheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClassForTypes(transactionalCandidateList, SubInheritedAnnotationClass.class));
|
||||
|
||||
// non-inherited class-level annotation; note: @Order is not inherited,
|
||||
// but findAnnotationDeclaringClassForTypes() should still find it on classes.
|
||||
List<Class<? extends Annotation>> orderCandidateList = Arrays.<Class<? extends Annotation>> asList(Order.class);
|
||||
assertEquals(NonInheritedAnnotationInterface.class,
|
||||
findAnnotationDeclaringClassForTypes(orderCandidateList, NonInheritedAnnotationInterface.class));
|
||||
assertNull(findAnnotationDeclaringClassForTypes(orderCandidateList, SubNonInheritedAnnotationInterface.class));
|
||||
assertEquals(NonInheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClassForTypes(orderCandidateList, NonInheritedAnnotationClass.class));
|
||||
assertEquals(NonInheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClassForTypes(orderCandidateList, SubNonInheritedAnnotationClass.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAnnotationDeclaringClassForTypesWithMultipleCandidateTypes() {
|
||||
|
||||
List<Class<? extends Annotation>> candidates = Arrays.<Class<? extends Annotation>> asList(Transactional.class,
|
||||
Order.class);
|
||||
|
||||
// no class-level annotation
|
||||
assertNull(findAnnotationDeclaringClassForTypes(candidates, NonAnnotatedInterface.class));
|
||||
assertNull(findAnnotationDeclaringClassForTypes(candidates, NonAnnotatedClass.class));
|
||||
|
||||
// inherited class-level annotation; note: @Transactional is inherited
|
||||
assertEquals(InheritedAnnotationInterface.class,
|
||||
findAnnotationDeclaringClassForTypes(candidates, InheritedAnnotationInterface.class));
|
||||
assertNull(findAnnotationDeclaringClassForTypes(candidates, SubInheritedAnnotationInterface.class));
|
||||
assertEquals(InheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClassForTypes(candidates, InheritedAnnotationClass.class));
|
||||
assertEquals(InheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClassForTypes(candidates, SubInheritedAnnotationClass.class));
|
||||
|
||||
// non-inherited class-level annotation; note: @Order is not inherited,
|
||||
// but findAnnotationDeclaringClassForTypes() should still find it on classes.
|
||||
assertEquals(NonInheritedAnnotationInterface.class,
|
||||
findAnnotationDeclaringClassForTypes(candidates, NonInheritedAnnotationInterface.class));
|
||||
assertNull(findAnnotationDeclaringClassForTypes(candidates, SubNonInheritedAnnotationInterface.class));
|
||||
assertEquals(NonInheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClassForTypes(candidates, NonInheritedAnnotationClass.class));
|
||||
assertEquals(NonInheritedAnnotationClass.class,
|
||||
findAnnotationDeclaringClassForTypes(candidates, SubNonInheritedAnnotationClass.class));
|
||||
|
||||
// class hierarchy mixed with @Transactional and @Order declarations
|
||||
assertEquals(TransactionalClass.class,
|
||||
findAnnotationDeclaringClassForTypes(candidates, TransactionalClass.class));
|
||||
assertEquals(TransactionalAndOrderedClass.class,
|
||||
findAnnotationDeclaringClassForTypes(candidates, TransactionalAndOrderedClass.class));
|
||||
assertEquals(TransactionalAndOrderedClass.class,
|
||||
findAnnotationDeclaringClassForTypes(candidates, SubTransactionalAndOrderedClass.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -216,18 +289,18 @@ public class AnnotationUtilsTests {
|
||||
}
|
||||
|
||||
|
||||
@Component(value="meta1")
|
||||
@Component(value = "meta1")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Meta1 {
|
||||
}
|
||||
|
||||
@Component(value="meta2")
|
||||
@Component(value = "meta2")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Meta2 {
|
||||
}
|
||||
|
||||
@Meta1
|
||||
@Component(value="local")
|
||||
@Component(value = "local")
|
||||
@Meta2
|
||||
static class HasLocalAndMetaComponentAnnotation {
|
||||
}
|
||||
@@ -332,6 +405,16 @@ public class AnnotationUtilsTests {
|
||||
public static class SubNonInheritedAnnotationClass extends NonInheritedAnnotationClass {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public static class TransactionalClass {
|
||||
}
|
||||
|
||||
@Order
|
||||
public static class TransactionalAndOrderedClass {
|
||||
}
|
||||
|
||||
public static class SubTransactionalAndOrderedClass extends TransactionalAndOrderedClass {
|
||||
}
|
||||
|
||||
public static interface InterfaceWithAnnotatedMethod {
|
||||
|
||||
@@ -353,10 +436,12 @@ public class AnnotationUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class AbstractDoesNotImplementInterfaceWithAnnotatedMethod implements InterfaceWithAnnotatedMethod {
|
||||
public abstract static class AbstractDoesNotImplementInterfaceWithAnnotatedMethod implements
|
||||
InterfaceWithAnnotatedMethod {
|
||||
}
|
||||
|
||||
public static class SubOfAbstractImplementsInterfaceWithAnnotatedMethod extends AbstractDoesNotImplementInterfaceWithAnnotatedMethod {
|
||||
public static class SubOfAbstractImplementsInterfaceWithAnnotatedMethod extends
|
||||
AbstractDoesNotImplementInterfaceWithAnnotatedMethod {
|
||||
|
||||
@Override
|
||||
public void foo() {
|
||||
|
||||
@@ -16,14 +16,6 @@
|
||||
|
||||
package org.springframework.util;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
@@ -36,6 +28,10 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
* Tests for {@link StreamUtils}.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -16,12 +16,6 @@
|
||||
|
||||
package org.springframework.util.xml;
|
||||
|
||||
import static org.mockito.BDDMockito.willAnswer;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
@@ -44,6 +38,8 @@ import org.xml.sax.ext.LexicalHandler;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
public abstract class AbstractStaxXMLReaderTestCase {
|
||||
|
||||
protected static XMLInputFactory inputFactory;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
package org.springframework.util.xml;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
@@ -29,6 +27,8 @@ import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
public class StaxEventXMLReaderTests extends AbstractStaxXMLReaderTestCase {
|
||||
|
||||
public static final String CONTENT = "<root xmlns='http://springframework.org/spring-ws'><child/></root>";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -18,23 +18,22 @@ package org.springframework.util.xml;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
public class StaxStreamXMLReaderTests extends AbstractStaxXMLReaderTestCase {
|
||||
|
||||
public static final String CONTENT = "<root xmlns='http://springframework.org/spring-ws'><child/></root>";
|
||||
|
||||
Reference in New Issue
Block a user