Polishing

(cherry picked from commit 02aca9c)
This commit is contained in:
Juergen Hoeller
2014-04-30 00:01:07 +02:00
parent d0c839f0eb
commit 1afdd9bd75
4 changed files with 55 additions and 59 deletions

View File

@@ -41,14 +41,15 @@ public class Spr10744Tests {
@Test @Test
public void testSpr10744() throws Exception { public void testSpr10744() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
MyTestScope scope = new MyTestScope(); context.getBeanFactory().registerScope("myTestScope", new MyTestScope());
context.getBeanFactory().registerScope("myTestScope", scope);
context.register(MyTestConfiguration.class); context.register(MyTestConfiguration.class);
context.refresh(); context.refresh();
Foo bean1 = context.getBean("foo", Foo.class); Foo bean1 = context.getBean("foo", Foo.class);
Foo bean2 = context.getBean("foo", Foo.class); Foo bean2 = context.getBean("foo", Foo.class);
assertThat(bean1, sameInstance(bean2)); assertThat(bean1, sameInstance(bean2));
// Should have created a single instance for the proxy
// Should not have invoked constructor for the proxy instance
assertThat(createCount, equalTo(0)); assertThat(createCount, equalTo(0));
assertThat(scopeCount, equalTo(0)); assertThat(scopeCount, equalTo(0));
@@ -118,9 +119,9 @@ public class Spr10744Tests {
@Configuration @Configuration
static class MyTestConfiguration extends MyConfiguration { static class MyTestConfiguration extends MyConfiguration {
@Override
@Scope(value = "myTestScope", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Bean @Bean
@Scope(value = "myTestScope", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Override
public Foo foo() { public Foo foo() {
return new Foo(); return new Foo();
} }

View File

@@ -70,8 +70,8 @@ public abstract class AnnotationUtils {
* Get a single {@link Annotation} of {@code annotationType} from the supplied * Get a single {@link Annotation} of {@code annotationType} from the supplied
* annotation: either the given annotation itself or a meta-annotation thereof. * annotation: either the given annotation itself or a meta-annotation thereof.
* @param ann the Annotation to check * @param ann the Annotation to check
* @param annotationType the annotation class to look for, both locally and as a meta-annotation * @param annotationType the annotation type to look for, both locally and as a meta-annotation
* @return the matching annotation or {@code null} if not found * @return the matching annotation, or {@code null} if none found
* @since 4.0 * @since 4.0
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -87,8 +87,8 @@ public abstract class AnnotationUtils {
* Method, Constructor or Field. Meta-annotations will be searched if the annotation * Method, Constructor or Field. Meta-annotations will be searched if the annotation
* is not declared locally on the supplied element. * is not declared locally on the supplied element.
* @param ae the Method, Constructor or Field from which to get the annotation * @param ae the Method, Constructor or Field from which to get the annotation
* @param annotationType the annotation class to look for, both locally and as a meta-annotation * @param annotationType the annotation type to look for, both locally and as a meta-annotation
* @return the matching annotation or {@code null} if not found * @return the matching annotation, or {@code null} if none found
* @since 3.1 * @since 3.1
*/ */
public static <T extends Annotation> T getAnnotation(AnnotatedElement ae, Class<T> annotationType) { public static <T extends Annotation> T getAnnotation(AnnotatedElement ae, Class<T> annotationType) {
@@ -119,7 +119,7 @@ public abstract class AnnotationUtils {
* Get a single {@link Annotation} of {@code annotationType} from the supplied {@link Method}. * Get a single {@link Annotation} of {@code annotationType} from the supplied {@link Method}.
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler. * <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
* @param method the method to look for annotations on * @param method the method to look for annotations on
* @param annotationType the annotation class to look for * @param annotationType the annotation type to look for
* @return the annotations found * @return the annotations found
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method) * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
*/ */
@@ -135,7 +135,7 @@ public abstract class AnnotationUtils {
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler. * <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
* @param method the method to look for annotations on * @param method the method to look for annotations on
* @param containerAnnotationType the class of the container that holds the annotations * @param containerAnnotationType the class of the container that holds the annotations
* @param annotationType the annotation class to look for * @param annotationType the annotation type to look for
* @return the annotations found * @return the annotations found
* @since 4.0 * @since 4.0
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method) * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
@@ -154,7 +154,7 @@ public abstract class AnnotationUtils {
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler. * <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
* @param annotatedElement the element to look for annotations on * @param annotatedElement the element to look for annotations on
* @param containerAnnotationType the class of the container that holds the annotations * @param containerAnnotationType the class of the container that holds the annotations
* @param annotationType the annotation class to look for * @param annotationType the annotation type to look for
* @return the annotations found * @return the annotations found
* @since 4.0 * @since 4.0
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method) * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
@@ -170,13 +170,13 @@ public abstract class AnnotationUtils {
/** /**
* Find a single {@link Annotation} of {@code annotationType} from the supplied * Find a single {@link Annotation} of {@code annotationType} from the supplied
* {@link Method}, traversing its super methods (i.e., from super classes and * {@link Method}, traversing its super methods (i.e., from superclasses and
* interfaces) if no annotation can be found on the given method itself. * interfaces) if no annotation can be found on the given method itself.
* <p>Annotations on methods are not inherited by default, so we need to handle * <p>Annotations on methods are not inherited by default, so we need to handle
* this explicitly. * this explicitly.
* @param method the method to look for annotations on * @param method the method to look for annotations on
* @param annotationType the annotation class to look for * @param annotationType the annotation type to look for
* @return the annotation found, or {@code null} if none found * @return the annotation found, or {@code null} if none
*/ */
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) { public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
A annotation = getAnnotation(method, annotationType); A annotation = getAnnotation(method, annotationType);
@@ -288,8 +288,7 @@ public abstract class AnnotationUtils {
} }
for (Annotation ann : clazz.getDeclaredAnnotations()) { for (Annotation ann : clazz.getDeclaredAnnotations()) {
if (!isInJavaLangAnnotationPackage(ann) && visited.add(ann)) { if (!isInJavaLangAnnotationPackage(ann) && visited.add(ann)) {
A annotation = findAnnotation(ann.annotationType(), annotationType, A annotation = findAnnotation(ann.annotationType(), annotationType, visited);
visited);
if (annotation != null) { if (annotation != null) {
return annotation; return annotation;
} }
@@ -312,8 +311,8 @@ public abstract class AnnotationUtils {
* <p>The standard {@link Class} API does not provide a mechanism for determining which class * <p>The standard {@link Class} API does not provide a mechanism for determining which class
* in an inheritance hierarchy actually declares an {@link Annotation}, so we need to handle * in an inheritance hierarchy actually declares an {@link Annotation}, so we need to handle
* this explicitly. * this explicitly.
* @param annotationType the annotation class to look for, both locally and as a meta-annotation * @param annotationType the annotation type to look for, both locally and as a meta-annotation
* @param clazz the class on which to check for the annotation, or {@code null} * @param clazz the class on which to check for the annotation (may be {@code null})
* @return the first {@link Class} in the inheritance hierarchy of the specified {@code clazz} * @return the first {@link Class} in the inheritance hierarchy of the specified {@code clazz}
* which declares an annotation for the specified {@code annotationType}, or {@code null} * which declares an annotation for the specified {@code annotationType}, or {@code null}
* if not found * if not found
@@ -509,8 +508,7 @@ public abstract class AnnotationUtils {
Annotation[] realAnnotations = (Annotation[]) value; Annotation[] realAnnotations = (Annotation[]) value;
AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length]; AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length];
for (int i = 0; i < realAnnotations.length; i++) { for (int i = 0; i < realAnnotations.length; i++) {
mappedAnnotations[i] = getAnnotationAttributes( mappedAnnotations[i] = getAnnotationAttributes(realAnnotations[i], classValuesAsString, true);
realAnnotations[i], classValuesAsString, true);
} }
attrs.put(method.getName(), mappedAnnotations); attrs.put(method.getName(), mappedAnnotations);
} }
@@ -634,7 +632,7 @@ public abstract class AnnotationUtils {
this.result.add((A) annotation); this.result.add((A) annotation);
} }
else if (ObjectUtils.nullSafeEquals(this.containerAnnotationType, annotation.annotationType())) { else if (ObjectUtils.nullSafeEquals(this.containerAnnotationType, annotation.annotationType())) {
result.addAll(Arrays.asList(getValue(annotation))); this.result.addAll(Arrays.asList(getValue(annotation)));
} }
else if (!isInJavaLangAnnotationPackage(annotation)) { else if (!isInJavaLangAnnotationPackage(annotation)) {
process(annotation.annotationType()); process(annotation.annotationType());
@@ -651,8 +649,8 @@ public abstract class AnnotationUtils {
return (A[]) method.invoke(annotation); return (A[]) method.invoke(annotation);
} }
catch (Exception ex) { catch (Exception ex) {
throw new IllegalStateException("Unable to read value from repeating annotation container " throw new IllegalStateException("Unable to read value from repeating annotation container " +
+ this.containerAnnotationType.getName(), ex); this.containerAnnotationType.getName(), ex);
} }
} }
} }

View File

@@ -29,8 +29,8 @@ import org.springframework.util.ReflectionUtils;
/** /**
* Oracle-specific implementation of the {@link org.springframework.jdbc.core.metadata.TableMetaDataProvider}. * Oracle-specific implementation of the {@link org.springframework.jdbc.core.metadata.TableMetaDataProvider}.
* Supports a feature for including synonyms in the metadata lookup. Also supports lookup of current schema using * Supports a feature for including synonyms in the metadata lookup. Also supports lookup of current schema
* the sys_context. * using the sys_context.
* *
* <p>Thanks to Mike Youngstrom and Bruce Campbell for submitting the original suggestion for the Oracle * <p>Thanks to Mike Youngstrom and Bruce Campbell for submitting the original suggestion for the Oracle
* current schema lookup implementation. * current schema lookup implementation.
@@ -128,7 +128,6 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
/* /*
* Oracle-based implementation for detecting the current schema. * Oracle-based implementation for detecting the current schema.
* @param databaseMetaData
*/ */
private void lookupDefaultSchema(DatabaseMetaData databaseMetaData) { private void lookupDefaultSchema(DatabaseMetaData databaseMetaData) {
try { try {

View File

@@ -28,30 +28,24 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.test.context.MetaAnnotationUtils.*;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import static org.springframework.test.context.MetaAnnotationUtils.*;
/** /**
* <p> * {@code TestContextManager} is the main entry point into the <em>Spring
* {@code TestContextManager} is the main entry point into the * TestContext Framework</em>, which provides support for loading and accessing
* <em>Spring TestContext Framework</em>, which provides support for loading and * {@link org.springframework.context.ApplicationContext application contexts},
* accessing {@link ApplicationContext application contexts}, dependency * dependency injection of test instances,
* injection of test instances, * {@link org.springframework.transaction.annotation.Transactional transactional}
* {@link org.springframework.transaction.annotation.Transactional * execution of test methods, etc.
* transactional} execution of test methods, etc. *
* </p> * <p>Specifically, a {@code TestContextManager} is responsible for managing a
* <p>
* Specifically, a {@code TestContextManager} is responsible for managing a
* single {@link TestContext} and signaling events to all registered * single {@link TestContext} and signaling events to all registered
* {@link TestExecutionListener TestExecutionListeners} at well defined test * {@link TestExecutionListener TestExecutionListeners} at well defined test
* execution points: * execution points:
* </p> *
* <ul> * <ul>
* <li>{@link #beforeTestClass() before test class execution}: prior to any * <li>{@link #beforeTestClass() before test class execution}: prior to any
* <em>before class methods</em> of a particular testing framework (e.g., JUnit * <em>before class methods</em> of a particular testing framework (e.g., JUnit
@@ -88,9 +82,10 @@ public class TestContextManager {
private static final Log logger = LogFactory.getLog(TestContextManager.class); private static final Log logger = LogFactory.getLog(TestContextManager.class);
/** /**
* Cache of Spring application contexts. This needs to be static, as tests * Cache of Spring application contexts.
* may be destroyed and recreated between running individual test methods, * <p>This needs to be static, since test instances may be destroyed and
* for example with JUnit. * recreated between invocations of individual test methods, as is the case
* with JUnit.
*/ */
static final ContextCache contextCache = new ContextCache(); static final ContextCache contextCache = new ContextCache();
@@ -100,7 +95,11 @@ public class TestContextManager {
/** /**
* Delegates to {@link #TestContextManager(Class, String)} with a value of * Construct a new {@code TestContextManager} for the specified {@linkplain Class test class}
* and automatically {@link #registerTestExecutionListeners register} the
* {@link TestExecutionListener TestExecutionListeners} configured for the test class
* via the {@link TestExecutionListeners &#064;TestExecutionListeners} annotation.
* <p>Delegates to {@link #TestContextManager(Class, String)} with a value of
* {@code null} for the default {@code ContextLoader} class name. * {@code null} for the default {@code ContextLoader} class name.
*/ */
public TestContextManager(Class<?> testClass) { public TestContextManager(Class<?> testClass) {
@@ -108,16 +107,14 @@ public class TestContextManager {
} }
/** /**
* Constructs a new {@code TestContextManager} for the specified {@linkplain Class * Construct a new {@code TestContextManager} for the specified {@linkplain Class test class}
* test class} and automatically {@link #registerTestExecutionListeners registers} the * and automatically {@link #registerTestExecutionListeners register} the
* {@link TestExecutionListener TestExecutionListeners} configured for the test class * {@link TestExecutionListener TestExecutionListeners} configured for the test class
* via the {@link TestExecutionListeners @TestExecutionListeners} annotation. * via the {@link TestExecutionListeners &#064;TestExecutionListeners} annotation.
* @param testClass the test class to be managed * @param testClass the test class to be managed
* @param defaultContextLoaderClassName the name of the default {@code ContextLoader} * @param defaultContextLoaderClassName the name of the default {@code ContextLoader} class
* class to use (may be {@code null}) * to use (may be {@code null})
* @see #registerTestExecutionListeners(TestExecutionListener...) * @see #registerTestExecutionListeners
* @deprecated Spring Framework 4.1 will introduce a bootstrap strategy for
* the TestContext framework at which point this constructor will be removed.
*/ */
@Deprecated @Deprecated
public TestContextManager(Class<?> testClass, String defaultContextLoaderClassName) { public TestContextManager(Class<?> testClass, String defaultContextLoaderClassName) {
@@ -125,9 +122,9 @@ public class TestContextManager {
registerTestExecutionListeners(retrieveTestExecutionListeners(testClass)); registerTestExecutionListeners(retrieveTestExecutionListeners(testClass));
} }
/** /**
* Returns the {@link TestContext} managed by this * Get the {@link TestContext} managed by this {@code TestContextManager}.
* {@code TestContextManager}.
*/ */
protected final TestContext getTestContext() { protected final TestContext getTestContext() {
return this.testContext; return this.testContext;
@@ -183,7 +180,8 @@ public class TestContextManager {
Class<TestExecutionListeners> annotationType = TestExecutionListeners.class; Class<TestExecutionListeners> annotationType = TestExecutionListeners.class;
List<Class<? extends TestExecutionListener>> classesList = new ArrayList<Class<? extends TestExecutionListener>>(); List<Class<? extends TestExecutionListener>> classesList = new ArrayList<Class<? extends TestExecutionListener>>();
AnnotationDescriptor<TestExecutionListeners> descriptor = findAnnotationDescriptor(clazz, annotationType); MetaAnnotationUtils.AnnotationDescriptor<TestExecutionListeners> descriptor =
MetaAnnotationUtils.findAnnotationDescriptor(clazz, annotationType);
// Use defaults? // Use defaults?
if (descriptor == null) { if (descriptor == null) {
@@ -223,8 +221,8 @@ public class TestContextManager {
classesList.addAll(0, Arrays.<Class<? extends TestExecutionListener>> asList(listenerClasses)); classesList.addAll(0, Arrays.<Class<? extends TestExecutionListener>> asList(listenerClasses));
} }
descriptor = (annAttrs.getBoolean("inheritListeners") ? findAnnotationDescriptor( descriptor = (annAttrs.getBoolean("inheritListeners") ? MetaAnnotationUtils.findAnnotationDescriptor(
descriptor.getRootDeclaringClass().getSuperclass(), annotationType) : null); descriptor.getRootDeclaringClass().getSuperclass(), annotationType) : null);
} }
} }