Polishing
This commit is contained in:
@@ -220,8 +220,8 @@ class TypeConverterDelegate {
|
||||
else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
|
||||
if (firstAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
|
||||
try {
|
||||
Constructor strCtor = requiredType.getConstructor(String.class);
|
||||
return (T) BeanUtils.instantiateClass(strCtor, convertedValue);
|
||||
Constructor<T> strCtor = requiredType.getConstructor(String.class);
|
||||
return BeanUtils.instantiateClass(strCtor, convertedValue);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
// proceed with field lookup
|
||||
@@ -331,7 +331,7 @@ class TypeConverterDelegate {
|
||||
* @param requiredType the type to find an editor for
|
||||
* @return the corresponding editor, or {@code null} if none
|
||||
*/
|
||||
private PropertyEditor findDefaultEditor(Class requiredType) {
|
||||
private PropertyEditor findDefaultEditor(Class<?> requiredType) {
|
||||
PropertyEditor editor = null;
|
||||
if (requiredType != null) {
|
||||
// No custom editor -> check BeanWrapperImpl's default editors.
|
||||
@@ -496,7 +496,7 @@ class TypeConverterDelegate {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Collection convertToTypedCollection(
|
||||
Collection original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
Collection original, String propertyName, Class<?> requiredType, TypeDescriptor typeDescriptor) {
|
||||
|
||||
if (!Collection.class.isAssignableFrom(requiredType)) {
|
||||
return original;
|
||||
@@ -578,7 +578,7 @@ class TypeConverterDelegate {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map convertToTypedMap(
|
||||
Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
Map original, String propertyName, Class<?> requiredType, TypeDescriptor typeDescriptor) {
|
||||
|
||||
if (!Map.class.isAssignableFrom(requiredType)) {
|
||||
return original;
|
||||
@@ -674,7 +674,7 @@ class TypeConverterDelegate {
|
||||
null);
|
||||
}
|
||||
|
||||
private boolean canCreateCopy(Class requiredType) {
|
||||
private boolean canCreateCopy(Class<?> requiredType) {
|
||||
return (!requiredType.isInterface() && !Modifier.isAbstract(requiredType.getModifiers()) &&
|
||||
Modifier.isPublic(requiredType.getModifiers()) && ClassUtils.hasConstructor(requiredType));
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DisposableBeanAdapter.class);
|
||||
|
||||
private static Class closeableInterface;
|
||||
private static Class<?> closeableInterface;
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -86,14 +86,14 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
|
||||
private final boolean nonPublicAccessAllowed;
|
||||
|
||||
private final AccessControlContext acc;
|
||||
|
||||
private String destroyMethodName;
|
||||
|
||||
private transient Method destroyMethod;
|
||||
|
||||
private List<DestructionAwareBeanPostProcessor> beanPostProcessors;
|
||||
|
||||
private final AccessControlContext acc;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new DisposableBeanAdapter for the given bean.
|
||||
@@ -150,9 +150,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
this.beanName = beanName;
|
||||
this.invokeDisposableBean = invokeDisposableBean;
|
||||
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
|
||||
this.acc = null;
|
||||
this.destroyMethodName = destroyMethodName;
|
||||
this.beanPostProcessors = postProcessors;
|
||||
this.acc = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.configuration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class Spr10744Tests {
|
||||
|
||||
private static int createCount = 0;
|
||||
|
||||
private static int scopeCount = 0;
|
||||
|
||||
|
||||
@Test
|
||||
public void testSpr10744() throws Exception {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.getBeanFactory().registerScope("myTestScope", new MyTestScope());
|
||||
context.register(MyTestConfiguration.class);
|
||||
context.refresh();
|
||||
|
||||
Foo bean1 = context.getBean("foo", Foo.class);
|
||||
Foo bean2 = context.getBean("foo", Foo.class);
|
||||
assertThat(bean1, sameInstance(bean2));
|
||||
|
||||
// Should have created a single instance for the proxy
|
||||
assertThat(createCount, equalTo(1));
|
||||
assertThat(scopeCount, equalTo(0));
|
||||
|
||||
// Proxy mode should create new scoped object on each method call
|
||||
bean1.getMessage();
|
||||
assertThat(createCount, equalTo(2));
|
||||
assertThat(scopeCount, equalTo(1));
|
||||
bean1.getMessage();
|
||||
assertThat(createCount, equalTo(3));
|
||||
assertThat(scopeCount, equalTo(2));
|
||||
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
||||
private static class MyTestScope implements org.springframework.beans.factory.config.Scope {
|
||||
|
||||
@Override
|
||||
public Object get(String name, ObjectFactory<?> objectFactory) {
|
||||
scopeCount++;
|
||||
return objectFactory.getObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object remove(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDestructionCallback(String name, Runnable callback) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveContextualObject(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConversationId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class Foo {
|
||||
|
||||
public Foo() {
|
||||
createCount++;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return "Hello";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class MyConfiguration {
|
||||
|
||||
@Bean
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class MyTestConfiguration extends MyConfiguration {
|
||||
|
||||
@Bean
|
||||
@Scope(value = "myTestScope", proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||
@Override
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -25,6 +25,7 @@ import java.util.WeakHashMap;
|
||||
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* General utility methods for working with annotations, handling bridge methods (which the compiler
|
||||
@@ -60,8 +61,8 @@ public abstract class AnnotationUtils {
|
||||
* Method, Constructor or Field. Meta-annotations will be searched if the annotation
|
||||
* is not declared locally on the supplied element.
|
||||
* @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
|
||||
* @return the matching annotation or {@code null} if not found
|
||||
* @param annotationType the annotation type to look for, both locally and as a meta-annotation
|
||||
* @return the matching annotation, or {@code null} if none found
|
||||
* @since 3.1
|
||||
*/
|
||||
public static <T extends Annotation> T getAnnotation(AnnotatedElement ae, Class<T> annotationType) {
|
||||
@@ -92,7 +93,7 @@ public abstract class AnnotationUtils {
|
||||
* Get a single {@link Annotation} of {@code annotationType} from the supplied {@link Method}.
|
||||
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
|
||||
* @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
|
||||
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
|
||||
*/
|
||||
@@ -115,8 +116,8 @@ public abstract class AnnotationUtils {
|
||||
* traversing its super methods 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 this explicitly.
|
||||
* @param method the method to look for annotations on
|
||||
* @param annotationType the annotation class to look for
|
||||
* @return the annotation found, or {@code null} if none found
|
||||
* @param annotationType the annotation type to look for
|
||||
* @return the annotation found, or {@code null} if none
|
||||
*/
|
||||
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
|
||||
A annotation = getAnnotation(method, annotationType);
|
||||
@@ -192,7 +193,7 @@ public abstract class AnnotationUtils {
|
||||
* with the interfaces that the superclass declares. Recursing up through the entire superclass
|
||||
* hierarchy if no match is found.
|
||||
* @param clazz the class 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
|
||||
*/
|
||||
public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
|
||||
@@ -215,11 +216,11 @@ public abstract class AnnotationUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
Class<?> superClass = clazz.getSuperclass();
|
||||
if (superClass == null || superClass.equals(Object.class)) {
|
||||
Class<?> superclass = clazz.getSuperclass();
|
||||
if (superclass == null || superclass.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
return findAnnotation(superClass, annotationType);
|
||||
return findAnnotation(superclass, annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,9 +233,8 @@ public abstract class AnnotationUtils {
|
||||
* <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
|
||||
* this explicitly.
|
||||
* @param annotationType the Class object corresponding to the annotation type
|
||||
* @param clazz the Class object corresponding to the class on which to check for the annotation,
|
||||
* or {@code null}
|
||||
* @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 (may be {@code null})
|
||||
* @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}
|
||||
* if not found
|
||||
@@ -248,8 +248,10 @@ public abstract class AnnotationUtils {
|
||||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
return (isAnnotationDeclaredLocally(annotationType, clazz)) ? clazz : findAnnotationDeclaringClass(
|
||||
annotationType, clazz.getSuperclass());
|
||||
if (isAnnotationDeclaredLocally(annotationType, clazz)) {
|
||||
return clazz;
|
||||
}
|
||||
return findAnnotationDeclaringClass(annotationType, clazz.getSuperclass());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -413,14 +415,13 @@ public abstract class AnnotationUtils {
|
||||
}
|
||||
if (nestedAnnotationsAsMap && value instanceof Annotation) {
|
||||
attrs.put(method.getName(),
|
||||
getAnnotationAttributes((Annotation) value, classValuesAsString, nestedAnnotationsAsMap));
|
||||
getAnnotationAttributes((Annotation) value, classValuesAsString, true));
|
||||
}
|
||||
else if (nestedAnnotationsAsMap && value instanceof Annotation[]) {
|
||||
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, true);
|
||||
}
|
||||
attrs.put(method.getName(), mappedAnnotations);
|
||||
}
|
||||
@@ -456,7 +457,8 @@ public abstract class AnnotationUtils {
|
||||
*/
|
||||
public static Object getValue(Annotation annotation, String attributeName) {
|
||||
try {
|
||||
Method method = annotation.annotationType().getDeclaredMethod(attributeName, new Class[0]);
|
||||
Method method = annotation.annotationType().getDeclaredMethod(attributeName);
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
return method.invoke(annotation);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
@@ -506,8 +508,7 @@ public abstract class AnnotationUtils {
|
||||
*/
|
||||
public static Object getDefaultValue(Class<? extends Annotation> annotationType, String attributeName) {
|
||||
try {
|
||||
Method method = annotationType.getDeclaredMethod(attributeName, new Class[0]);
|
||||
return method.getDefaultValue();
|
||||
return annotationType.getDeclaredMethod(attributeName).getDefaultValue();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2014 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,6 +18,7 @@ package org.springframework.core.env;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -53,21 +54,22 @@ public abstract class EnumerablePropertySource<T> extends PropertySource<T> {
|
||||
super(name, source);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the names of all properties contained by the {@linkplain #getSource()
|
||||
* source} object (never {@code null}).
|
||||
* Return the names of all properties contained by the
|
||||
* {@linkplain #getSource() source} object (never {@code null}).
|
||||
*/
|
||||
public abstract String[] getPropertyNames();
|
||||
|
||||
/**
|
||||
* Return whether this {@code PropertySource} contains a property with the given name.
|
||||
* <p>This implementation checks for the presence of the given name within
|
||||
* the {@link #getPropertyNames()} array.
|
||||
* @param name the property to find
|
||||
* <p>This implementation checks for the presence of the given name within the
|
||||
* {@link #getPropertyNames()} array.
|
||||
* @param name the name of the property to find
|
||||
*/
|
||||
public boolean containsProperty(String name) {
|
||||
Assert.notNull(name, "property name must not be null");
|
||||
for (String candidate : this.getPropertyNames()) {
|
||||
Assert.notNull(name, "Property name must not be null");
|
||||
for (String candidate : getPropertyNames()) {
|
||||
if (candidate.equals(name)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("PropertySource [%s] contains '%s'", getName(), name));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2014 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,7 +18,9 @@ package org.springframework.core.env;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class representing a source of name/value property pairs. The underlying
|
||||
@@ -55,12 +57,13 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public abstract class PropertySource<T> {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected final String name;
|
||||
|
||||
protected final T source;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code PropertySource} with the given name and source object.
|
||||
*/
|
||||
@@ -74,15 +77,15 @@ public abstract class PropertySource<T> {
|
||||
/**
|
||||
* Create a new {@code PropertySource} with the given name and with a new {@code Object}
|
||||
* instance as the underlying source.
|
||||
* <p>Often useful in testing scenarios when creating
|
||||
* anonymous implementations that never query an actual source, but rather return
|
||||
* hard-coded values.
|
||||
* <p>Often useful in testing scenarios when creating anonymous implementations that
|
||||
* never query an actual source but rather return hard-coded values.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertySource(String name) {
|
||||
this(name, (T) new Object());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of this {@code PropertySource}
|
||||
*/
|
||||
@@ -94,91 +97,75 @@ public abstract class PropertySource<T> {
|
||||
* Return the underlying source object for this {@code PropertySource}.
|
||||
*/
|
||||
public T getSource() {
|
||||
return source;
|
||||
return this.source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this {@code PropertySource} contains the given name.
|
||||
* <p>This implementation simply checks for a null return value
|
||||
* from {@link #getProperty(String)}. Subclasses may wish to
|
||||
* implement a more efficient algorithm if possible.
|
||||
* <p>This implementation simply checks for a {@code null} return value
|
||||
* from {@link #getProperty(String)}. Subclasses may wish to implement
|
||||
* a more efficient algorithm if possible.
|
||||
* @param name the property name to find
|
||||
*/
|
||||
public boolean containsProperty(String name) {
|
||||
return this.getProperty(name) != null;
|
||||
return (getProperty(name) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value associated with the given name, {@code null} if not found.
|
||||
* Return the value associated with the given name,
|
||||
* or {@code null} if not found.
|
||||
* @param name the property to find
|
||||
* @see PropertyResolver#getRequiredProperty(String)
|
||||
*/
|
||||
public abstract Object getProperty(String name);
|
||||
|
||||
/**
|
||||
* Return a hashcode derived from the {@code name} property of this {@code PropertySource}
|
||||
* object.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This {@code PropertySource} object is equal to the given object if:
|
||||
* <ul>
|
||||
* <li>they are the same instance
|
||||
* <li>the {@code name} properties for both objects are equal
|
||||
* <li>they are the same instance
|
||||
* <li>the {@code name} properties for both objects are equal
|
||||
* </ul>
|
||||
*
|
||||
* <P>No properties other than {@code name} are evaluated.
|
||||
* <p>No properties other than {@code name} are evaluated.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (!(obj instanceof PropertySource))
|
||||
return false;
|
||||
PropertySource<?> other = (PropertySource<?>) obj;
|
||||
if (this.name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!this.name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
return (this == obj || (obj instanceof PropertySource &&
|
||||
ObjectUtils.nullSafeEquals(this.name, ((PropertySource<?>) obj).name)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash code derived from the {@code name} property
|
||||
* of this {@code PropertySource} object.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce concise output (type and name) if the current log level does not include
|
||||
* debug. If debug is enabled, produce verbose output including hashcode of the
|
||||
* debug. If debug is enabled, produce verbose output including the hash code of the
|
||||
* PropertySource instance and every name/value property pair.
|
||||
*
|
||||
* This variable verbosity is useful as a property source such as system properties
|
||||
* <p>This variable verbosity is useful as a property source such as system properties
|
||||
* or environment variables may contain an arbitrary number of property pairs,
|
||||
* potentially leading to difficult to read exception and log messages.
|
||||
*
|
||||
* @see Log#isDebugEnabled()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
return String.format("%s@%s [name='%s', properties=%s]",
|
||||
this.getClass().getSimpleName(), System.identityHashCode(this), this.name, this.source);
|
||||
getClass().getSimpleName(), System.identityHashCode(this), this.name, this.source);
|
||||
}
|
||||
else {
|
||||
return String.format("%s [name='%s']", getClass().getSimpleName(), this.name);
|
||||
}
|
||||
|
||||
return String.format("%s [name='%s']",
|
||||
this.getClass().getSimpleName(), this.name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a {@code PropertySource} implementation intended for collection comparison purposes only.
|
||||
*
|
||||
* <p>Primarily for internal use, but given a collection of {@code PropertySource} objects, may be
|
||||
* used as follows:
|
||||
* <pre class="code">
|
||||
@@ -189,11 +176,9 @@ public abstract class PropertySource<T> {
|
||||
* assert sources.contains(PropertySource.named("sourceB"));
|
||||
* assert !sources.contains(PropertySource.named("sourceC"));
|
||||
* }</pre>
|
||||
*
|
||||
* The returned {@code PropertySource} will throw {@code UnsupportedOperationException}
|
||||
* if any methods other than {@code equals(Object)}, {@code hashCode()}, and {@code toString()}
|
||||
* are called.
|
||||
*
|
||||
* @param name the name of the comparison {@code PropertySource} to be created and returned.
|
||||
*/
|
||||
public static PropertySource<?> named(String name) {
|
||||
@@ -209,7 +194,6 @@ public abstract class PropertySource<T> {
|
||||
* {@code ApplicationContext}. In such cases, a stub should be used to hold the
|
||||
* intended default position/order of the property source, then be replaced
|
||||
* during context refresh.
|
||||
*
|
||||
* @see org.springframework.context.support.AbstractApplicationContext#initPropertySources()
|
||||
* @see org.springframework.web.context.support.StandardServletEnvironment
|
||||
* @see org.springframework.web.context.support.ServletContextPropertySource
|
||||
@@ -221,7 +205,7 @@ public abstract class PropertySource<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Always return {@code null}.
|
||||
* Always returns {@code null}.
|
||||
*/
|
||||
@Override
|
||||
public String getProperty(String name) {
|
||||
@@ -236,8 +220,7 @@ public abstract class PropertySource<T> {
|
||||
static class ComparisonPropertySource extends StubPropertySource {
|
||||
|
||||
private static final String USAGE_ERROR =
|
||||
"ComparisonPropertySource instances are for collection comparison " +
|
||||
"use only";
|
||||
"ComparisonPropertySource instances are for use with collection comparison only";
|
||||
|
||||
public ComparisonPropertySource(String name) {
|
||||
super(name);
|
||||
|
||||
@@ -29,8 +29,8 @@ import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* the sys_context.
|
||||
* Supports a feature for including synonyms in the metadata lookup. Also supports lookup of current schema
|
||||
* using the sys_context.
|
||||
*
|
||||
* <p>Thanks to Mike Youngstrom and Bruce Campbell for submitting the original suggestion for the Oracle
|
||||
* current schema lookup implementation.
|
||||
@@ -56,9 +56,10 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
|
||||
lookupDefaultSchema(databaseMetaData);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getDefaultSchema() {
|
||||
if (defaultSchema != null) {
|
||||
if (this.defaultSchema != null) {
|
||||
return defaultSchema;
|
||||
}
|
||||
return super.getDefaultSchema();
|
||||
@@ -107,7 +108,7 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
|
||||
ReflectionUtils.makeAccessible(getIncludeSynonyms);
|
||||
originalValueForIncludeSynonyms = (Boolean) getIncludeSynonyms.invoke(con);
|
||||
|
||||
setIncludeSynonyms = con.getClass().getMethod("setIncludeSynonyms", new Class[] {boolean.class});
|
||||
setIncludeSynonyms = con.getClass().getMethod("setIncludeSynonyms", boolean.class);
|
||||
ReflectionUtils.makeAccessible(setIncludeSynonyms);
|
||||
setIncludeSynonyms.invoke(con, Boolean.TRUE);
|
||||
}
|
||||
@@ -126,9 +127,7 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
|
||||
}
|
||||
|
||||
/*
|
||||
* Oracle implementation for detecting current schema
|
||||
*
|
||||
* @param databaseMetaData
|
||||
* Oracle-based implementation for detecting the current schema.
|
||||
*/
|
||||
private void lookupDefaultSchema(DatabaseMetaData databaseMetaData) {
|
||||
try {
|
||||
@@ -144,7 +143,9 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
|
||||
cstmt.close();
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,27 +28,24 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* {@code TestContextManager} is the main entry point into the
|
||||
* <em>Spring TestContext Framework</em>, which provides support for loading and
|
||||
* accessing {@link ApplicationContext application contexts}, dependency
|
||||
* injection of test instances,
|
||||
* {@link org.springframework.transaction.annotation.Transactional
|
||||
* transactional} execution of test methods, etc.
|
||||
* </p>
|
||||
* <p>
|
||||
* Specifically, a {@code TestContextManager} is responsible for managing a
|
||||
* {@code TestContextManager} is the main entry point into the <em>Spring
|
||||
* TestContext Framework</em>, which provides support for loading and accessing
|
||||
* {@link org.springframework.context.ApplicationContext application contexts},
|
||||
* dependency injection of test instances,
|
||||
* {@link org.springframework.transaction.annotation.Transactional transactional}
|
||||
* execution of test methods, etc.
|
||||
*
|
||||
* <p>Specifically, a {@code TestContextManager} is responsible for managing a
|
||||
* single {@link TestContext} and signaling events to all registered
|
||||
* {@link TestExecutionListener TestExecutionListeners} at well defined test
|
||||
* execution points:
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #beforeTestClass() before test class execution}: prior to any
|
||||
* <em>before class methods</em> of a particular testing framework (e.g., JUnit
|
||||
@@ -85,9 +82,10 @@ public class TestContextManager {
|
||||
private static final Log logger = LogFactory.getLog(TestContextManager.class);
|
||||
|
||||
/**
|
||||
* Cache of Spring application contexts. This needs to be static, as tests
|
||||
* may be destroyed and recreated between running individual test methods,
|
||||
* for example with JUnit.
|
||||
* Cache of Spring application contexts.
|
||||
* <p>This needs to be static, since test instances may be destroyed and
|
||||
* recreated between invocations of individual test methods, as is the case
|
||||
* with JUnit.
|
||||
*/
|
||||
static final ContextCache contextCache = new ContextCache();
|
||||
|
||||
@@ -97,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 @TestExecutionListeners} annotation.
|
||||
* <p>Delegates to {@link #TestContextManager(Class, String)} with a value of
|
||||
* {@code null} for the default {@code ContextLoader} class name.
|
||||
*/
|
||||
public TestContextManager(Class<?> testClass) {
|
||||
@@ -105,23 +107,23 @@ public class TestContextManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code TestContextManager} for the specified {@linkplain Class
|
||||
* test class} and automatically {@link #registerTestExecutionListeners registers} the
|
||||
* 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 @TestExecutionListeners} annotation.
|
||||
* @param testClass the test class to be managed
|
||||
* @param defaultContextLoaderClassName the name of the default {@code ContextLoader}
|
||||
* class to use (may be {@code null})
|
||||
* @see #registerTestExecutionListeners(TestExecutionListener...)
|
||||
* @param defaultContextLoaderClassName the name of the default {@code ContextLoader} class
|
||||
* to use (may be {@code null})
|
||||
* @see #registerTestExecutionListeners
|
||||
*/
|
||||
public TestContextManager(Class<?> testClass, String defaultContextLoaderClassName) {
|
||||
this.testContext = new TestContext(testClass, contextCache, defaultContextLoaderClassName);
|
||||
registerTestExecutionListeners(retrieveTestExecutionListeners(testClass));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the {@link TestContext} managed by this
|
||||
* {@code TestContextManager}.
|
||||
* Get the {@link TestContext} managed by this {@code TestContextManager}.
|
||||
*/
|
||||
protected final TestContext getTestContext() {
|
||||
return this.testContext;
|
||||
@@ -183,7 +185,8 @@ public class TestContextManager {
|
||||
logger.debug("@TestExecutionListeners is not present for class [" + clazz + "]: using defaults.");
|
||||
}
|
||||
classesList.addAll(getDefaultTestExecutionListenerClasses());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// Traverse the class hierarchy...
|
||||
while (declaringClass != null) {
|
||||
TestExecutionListeners testExecutionListeners = declaringClass.getAnnotation(annotationType);
|
||||
@@ -201,7 +204,8 @@ public class TestContextManager {
|
||||
ObjectUtils.nullSafeToString(listenerClasses));
|
||||
logger.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
} else if (!ObjectUtils.isEmpty(valueListenerClasses)) {
|
||||
}
|
||||
else if (!ObjectUtils.isEmpty(valueListenerClasses)) {
|
||||
listenerClasses = valueListenerClasses;
|
||||
}
|
||||
|
||||
@@ -264,7 +268,7 @@ public class TestContextManager {
|
||||
* @see #getTestExecutionListeners()
|
||||
*/
|
||||
public void beforeTestClass() throws Exception {
|
||||
final Class<?> testClass = getTestContext().getTestClass();
|
||||
Class<?> testClass = getTestContext().getTestClass();
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("beforeTestClass(): class [" + testClass + "]");
|
||||
}
|
||||
@@ -421,7 +425,7 @@ public class TestContextManager {
|
||||
* @see #getTestExecutionListeners()
|
||||
*/
|
||||
public void afterTestClass() throws Exception {
|
||||
final Class<?> testClass = getTestContext().getTestClass();
|
||||
Class<?> testClass = getTestContext().getTestClass();
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("afterTestClass(): class [" + testClass + "]");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2014 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,9 +16,8 @@
|
||||
|
||||
package org.springframework.web.context.support;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
|
||||
@@ -26,18 +25,17 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AnnotationConfigWebApplicationContextTests {
|
||||
|
||||
@Test
|
||||
public void registerSingleClass() {
|
||||
AnnotationConfigWebApplicationContext ctx =
|
||||
new AnnotationConfigWebApplicationContext();
|
||||
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
|
||||
ctx.register(Config.class);
|
||||
ctx.refresh();
|
||||
|
||||
@@ -47,8 +45,7 @@ public class AnnotationConfigWebApplicationContextTests {
|
||||
|
||||
@Test
|
||||
public void configLocationWithSingleClass() {
|
||||
AnnotationConfigWebApplicationContext ctx =
|
||||
new AnnotationConfigWebApplicationContext();
|
||||
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
|
||||
ctx.setConfigLocation(Config.class.getName());
|
||||
ctx.refresh();
|
||||
|
||||
@@ -56,10 +53,19 @@ public class AnnotationConfigWebApplicationContextTests {
|
||||
assertNotNull(bean);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configLocationWithBasePackage() {
|
||||
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
|
||||
ctx.setConfigLocation("org.springframework.web.context.support");
|
||||
ctx.refresh();
|
||||
|
||||
TestBean bean = ctx.getBean(TestBean.class);
|
||||
assertNotNull(bean);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withBeanNameGenerator() {
|
||||
AnnotationConfigWebApplicationContext ctx =
|
||||
new AnnotationConfigWebApplicationContext();
|
||||
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
|
||||
ctx.setBeanNameGenerator(new AnnotationBeanNameGenerator() {
|
||||
@Override
|
||||
public String generateBeanName(BeanDefinition definition,
|
||||
@@ -75,14 +81,15 @@ public class AnnotationConfigWebApplicationContextTests {
|
||||
|
||||
@Configuration("myConfig")
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public TestBean myTestBean() {
|
||||
return new TestBean();
|
||||
}
|
||||
}
|
||||
|
||||
static class NotConfigurationAnnotated { }
|
||||
|
||||
static class TestBean { }
|
||||
static class TestBean {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user