[SPR-6184] Simplifying ContextLoader implmementation:

- Removed AbstractGenericContextLoader's createGenericApplicationContext() method.
- AnnotationConfigContextLoader now uses an AnnotatedBeanDefinitionReader instead of working with an AnnotationConfigApplicationContext.
- AnnotationConfigContextLoader now uses the supplied GenericApplicationContext to load configuration classes.
This commit is contained in:
Sam Brannen 2011-05-06 12:05:56 +00:00
parent c91ab1ad6e
commit ddc9bbb555
4 changed files with 30 additions and 53 deletions

View File

@ -137,8 +137,8 @@ abstract class ContextLoaderUtils {
}
try {
ContextConfiguration contextConfiguration = clazz.getAnnotation(annotationType);
if (logger.isTraceEnabled()) {
ContextConfiguration contextConfiguration = clazz.getAnnotation(annotationType);
logger.trace("Using default ContextLoader class [" + defaultContextLoaderClassName
+ "] for @ContextConfiguration [" + contextConfiguration + "] and class [" + clazz + "]");
}

View File

@ -25,6 +25,9 @@ package org.springframework.test.context;
* resource locations; as of Spring 3.1 context loaders may choose to
* support either String-based or Class-based resources (but not both).
*
* <p>TODO Document how classes are converted into String[] locations
* and passed into the corresponding methods in the ContextLoader API.
*
* <p>If a context loader does not implement this interface it is assumed
* that the loader supports String-based resource locations.
*

View File

@ -28,15 +28,17 @@ import org.springframework.util.StringUtils;
/**
* Abstract, generic extension of {@link AbstractContextLoader} which loads a
* {@link GenericApplicationContext} from the <em>locations</em> provided to
* {@link #loadContext(String...)}.
* {@link #loadContext loadContext()}.
*
* <p>Concrete subclasses must provide an appropriate
* {@link #createBeanDefinitionReader(GenericApplicationContext) BeanDefinitionReader}.
* <p>Concrete subclasses must provide an appropriate implementation of
* {@link #createBeanDefinitionReader createBeanDefinitionReader()},
* potentially overriding {@link #loadBeanDefinitions loadBeanDefinitions()}
* in addition.
*
* @author Sam Brannen
* @author Juergen Hoeller
* @since 2.5
* @see #loadContext(String...)
* @see #loadContext
*/
public abstract class AbstractGenericContextLoader extends AbstractContextLoader {
@ -47,8 +49,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
* Loads a Spring ApplicationContext from the supplied <code>locations</code>.
* <p>Implementation details:
* <ul>
* <li>Delegates to {@link #createGenericApplicationContext()} to
* create a {@link GenericApplicationContext} instance.</li>
* <li>Creates a {@link GenericApplicationContext} instance.</li>
* <li>Calls {@link #prepareContext(GenericApplicationContext)} to
* prepare the context.</li>
* <li>Calls {@link #customizeBeanFactory(DefaultListableBeanFactory)} to
@ -72,7 +73,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
logger.debug(String.format("Loading ApplicationContext for locations [%s].",
StringUtils.arrayToCommaDelimitedString(locations)));
}
GenericApplicationContext context = createGenericApplicationContext();
GenericApplicationContext context = new GenericApplicationContext();
prepareContext(context);
customizeBeanFactory(context.getDefaultListableBeanFactory());
loadBeanDefinitions(context, locations);
@ -83,20 +84,6 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
return context;
}
/**
* Factory method for creating a new {@link GenericApplicationContext}
* to be used by this <code>ContextLoader</code>.
* <p>The default implementation returns an instance of
* {@link GenericApplicationContext}. Can be overridden in subclasses
* to return a specific subclass of <code>GenericApplicationContext</code>.
* @return a new <code>GenericApplicationContext</code>
* @since 3.1
* @see #loadContext
*/
protected GenericApplicationContext createGenericApplicationContext() {
return new GenericApplicationContext();
}
/**
* Prepare the {@link GenericApplicationContext} created by this <code>ContextLoader</code>.
* Called <i>before</> bean definitions are read.
@ -132,10 +119,10 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
* {@link BeanDefinitionReader#loadBeanDefinitions(String) load} the
* bean definitions.
* <p>Subclasses must provide an appropriate implementation of
* {@link #createBeanDefinitionReader}.
* Alternatively subclasses may provide a <em>no-op</em> implementation
* of {@link #createBeanDefinitionReader} and override this method to
* provide a custom strategy for loading or registering bean definitions.
* {@link #createBeanDefinitionReader}. Alternatively subclasses may
* provide a <em>no-op</em> implementation of {@link #createBeanDefinitionReader}
* and override this method to provide a custom strategy for loading or
* registering bean definitions.
* @param context the context into which the bean definitions should be loaded
* @param locations the resource locations from which to load the bean definitions
* @since 3.1
@ -147,8 +134,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
/**
* Factory method for creating a new {@link BeanDefinitionReader} for
* loading bean definitions into the supplied
* {@link GenericApplicationContext context}.
* loading bean definitions into the supplied {@link GenericApplicationContext context}.
* @param context the context for which the BeanDefinitionReader should be created
* @return a BeanDefinitionReader for the supplied context
* @see #loadBeanDefinitions

View File

@ -19,7 +19,7 @@ package org.springframework.test.context.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.test.context.ContextLoader;
import org.springframework.util.Assert;
@ -27,8 +27,7 @@ import org.springframework.util.ObjectUtils;
/**
* Concrete implementation of {@link AbstractGenericContextLoader} which
* creates an {@link AnnotationConfigApplicationContext} and registers
* bean definitions from
* registers bean definitions from
* {@link org.springframework.context.annotation.Configuration configuration classes}.
*
* <p>This <code>ContextLoader</code> supports class-based context configuration
@ -46,44 +45,33 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader
private static final Log logger = LogFactory.getLog(AnnotationConfigContextLoader.class);
/**
* Creates a new {@link AnnotationConfigApplicationContext}.
*/
@Override
protected GenericApplicationContext createGenericApplicationContext() {
return new AnnotationConfigApplicationContext();
}
/**
* Registers {@link org.springframework.context.annotation.Configuration configuration classes}
* in the supplied {@link AnnotationConfigApplicationContext} from the specified
* in the supplied {@link GenericApplicationContext context} from the specified
* class names.
*
* <p>Each class name must be the <em>fully qualified class name</em> of an
* annotated configuration class, component, or feature specification. The
* <code>AnnotationConfigApplicationContext</code> assumes the responsibility
* of loading the appropriate bean definitions.
* annotated configuration class, component, or feature specification. An
* {@link AnnotatedBeanDefinitionReader} is used to register the appropriate
* bean definitions.
*
* <p>Note that this method does not call {@link #createBeanDefinitionReader}
* since <code>AnnotatedBeanDefinitionReader</code> is not an instance of
* {@link BeanDefinitionReader}.
*
* <p>Note that this method does not call {@link #createBeanDefinitionReader}.
* @param context the context in which the configuration classes should be registered
* @param classNames the names of configuration classes to register in the context
* @throws IllegalArgumentException if the supplied context is not an instance of
* <code>AnnotationConfigApplicationContext</code> or if a supplied class name
* does not represent a class
* @see #createGenericApplicationContext()
* @throws IllegalArgumentException if a supplied class name does not represent a class
*/
@Override
protected void loadBeanDefinitions(GenericApplicationContext context, String... classNames) {
Assert.isInstanceOf(AnnotationConfigApplicationContext.class, context,
"context must be an instance of AnnotationConfigApplicationContext");
Class<?>[] configClasses = new Class<?>[classNames.length];
for (int i = 0; i < classNames.length; i++) {
String className = classNames[i];
try {
configClasses[i] = (Class<?>) getClass().getClassLoader().loadClass(className);
configClasses[i] = (Class<?>) context.getClassLoader().loadClass(className);
}
catch (ClassNotFoundException e) {
throw new IllegalArgumentException(String.format(
@ -94,7 +82,7 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader
if (logger.isDebugEnabled()) {
logger.debug("Registering configuration classes: " + ObjectUtils.nullSafeToString(configClasses));
}
((AnnotationConfigApplicationContext) context).register(configClasses);
new AnnotatedBeanDefinitionReader(context).register(configClasses);
}
/**