提交 ddc9bbb5 编写于 作者: S Sam Brannen

[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.
上级 c91ab1ad
...@@ -137,8 +137,8 @@ abstract class ContextLoaderUtils { ...@@ -137,8 +137,8 @@ abstract class ContextLoaderUtils {
} }
try { try {
ContextConfiguration contextConfiguration = clazz.getAnnotation(annotationType);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
ContextConfiguration contextConfiguration = clazz.getAnnotation(annotationType);
logger.trace("Using default ContextLoader class [" + defaultContextLoaderClassName logger.trace("Using default ContextLoader class [" + defaultContextLoaderClassName
+ "] for @ContextConfiguration [" + contextConfiguration + "] and class [" + clazz + "]"); + "] for @ContextConfiguration [" + contextConfiguration + "] and class [" + clazz + "]");
} }
......
...@@ -25,6 +25,9 @@ package org.springframework.test.context; ...@@ -25,6 +25,9 @@ package org.springframework.test.context;
* resource locations; as of Spring 3.1 context loaders may choose to * resource locations; as of Spring 3.1 context loaders may choose to
* support either String-based or Class-based resources (but not both). * 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 * <p>If a context loader does not implement this interface it is assumed
* that the loader supports String-based resource locations. * that the loader supports String-based resource locations.
* *
......
...@@ -28,15 +28,17 @@ import org.springframework.util.StringUtils; ...@@ -28,15 +28,17 @@ import org.springframework.util.StringUtils;
/** /**
* Abstract, generic extension of {@link AbstractContextLoader} which loads a * Abstract, generic extension of {@link AbstractContextLoader} which loads a
* {@link GenericApplicationContext} from the <em>locations</em> provided to * {@link GenericApplicationContext} from the <em>locations</em> provided to
* {@link #loadContext(String...)}. * {@link #loadContext loadContext()}.
* *
* <p>Concrete subclasses must provide an appropriate * <p>Concrete subclasses must provide an appropriate implementation of
* {@link #createBeanDefinitionReader(GenericApplicationContext) BeanDefinitionReader}. * {@link #createBeanDefinitionReader createBeanDefinitionReader()},
* potentially overriding {@link #loadBeanDefinitions loadBeanDefinitions()}
* in addition.
* *
* @author Sam Brannen * @author Sam Brannen
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.5 * @since 2.5
* @see #loadContext(String...) * @see #loadContext
*/ */
public abstract class AbstractGenericContextLoader extends AbstractContextLoader { public abstract class AbstractGenericContextLoader extends AbstractContextLoader {
...@@ -47,8 +49,7 @@ 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>. * Loads a Spring ApplicationContext from the supplied <code>locations</code>.
* <p>Implementation details: * <p>Implementation details:
* <ul> * <ul>
* <li>Delegates to {@link #createGenericApplicationContext()} to * <li>Creates a {@link GenericApplicationContext} instance.</li>
* create a {@link GenericApplicationContext} instance.</li>
* <li>Calls {@link #prepareContext(GenericApplicationContext)} to * <li>Calls {@link #prepareContext(GenericApplicationContext)} to
* prepare the context.</li> * prepare the context.</li>
* <li>Calls {@link #customizeBeanFactory(DefaultListableBeanFactory)} to * <li>Calls {@link #customizeBeanFactory(DefaultListableBeanFactory)} to
...@@ -72,7 +73,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader ...@@ -72,7 +73,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
logger.debug(String.format("Loading ApplicationContext for locations [%s].", logger.debug(String.format("Loading ApplicationContext for locations [%s].",
StringUtils.arrayToCommaDelimitedString(locations))); StringUtils.arrayToCommaDelimitedString(locations)));
} }
GenericApplicationContext context = createGenericApplicationContext(); GenericApplicationContext context = new GenericApplicationContext();
prepareContext(context); prepareContext(context);
customizeBeanFactory(context.getDefaultListableBeanFactory()); customizeBeanFactory(context.getDefaultListableBeanFactory());
loadBeanDefinitions(context, locations); loadBeanDefinitions(context, locations);
...@@ -83,20 +84,6 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader ...@@ -83,20 +84,6 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
return context; 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>. * Prepare the {@link GenericApplicationContext} created by this <code>ContextLoader</code>.
* Called <i>before</> bean definitions are read. * Called <i>before</> bean definitions are read.
...@@ -132,10 +119,10 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader ...@@ -132,10 +119,10 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
* {@link BeanDefinitionReader#loadBeanDefinitions(String) load} the * {@link BeanDefinitionReader#loadBeanDefinitions(String) load} the
* bean definitions. * bean definitions.
* <p>Subclasses must provide an appropriate implementation of * <p>Subclasses must provide an appropriate implementation of
* {@link #createBeanDefinitionReader}. * {@link #createBeanDefinitionReader}. Alternatively subclasses may
* Alternatively subclasses may provide a <em>no-op</em> implementation * provide a <em>no-op</em> implementation of {@link #createBeanDefinitionReader}
* of {@link #createBeanDefinitionReader} and override this method to * and override this method to provide a custom strategy for loading or
* provide a custom strategy for loading or registering bean definitions. * registering bean definitions.
* @param context the context into which the bean definitions should be loaded * @param context the context into which the bean definitions should be loaded
* @param locations the resource locations from which to load the bean definitions * @param locations the resource locations from which to load the bean definitions
* @since 3.1 * @since 3.1
...@@ -147,8 +134,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader ...@@ -147,8 +134,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
/** /**
* Factory method for creating a new {@link BeanDefinitionReader} for * Factory method for creating a new {@link BeanDefinitionReader} for
* loading bean definitions into the supplied * loading bean definitions into the supplied {@link GenericApplicationContext context}.
* {@link GenericApplicationContext context}.
* @param context the context for which the BeanDefinitionReader should be created * @param context the context for which the BeanDefinitionReader should be created
* @return a BeanDefinitionReader for the supplied context * @return a BeanDefinitionReader for the supplied context
* @see #loadBeanDefinitions * @see #loadBeanDefinitions
......
...@@ -19,7 +19,7 @@ package org.springframework.test.context.support; ...@@ -19,7 +19,7 @@ package org.springframework.test.context.support;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.BeanDefinitionReader; 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.context.support.GenericApplicationContext;
import org.springframework.test.context.ContextLoader; import org.springframework.test.context.ContextLoader;
import org.springframework.util.Assert; import org.springframework.util.Assert;
...@@ -27,8 +27,7 @@ import org.springframework.util.ObjectUtils; ...@@ -27,8 +27,7 @@ import org.springframework.util.ObjectUtils;
/** /**
* Concrete implementation of {@link AbstractGenericContextLoader} which * Concrete implementation of {@link AbstractGenericContextLoader} which
* creates an {@link AnnotationConfigApplicationContext} and registers * registers bean definitions from
* bean definitions from
* {@link org.springframework.context.annotation.Configuration configuration classes}. * {@link org.springframework.context.annotation.Configuration configuration classes}.
* *
* <p>This <code>ContextLoader</code> supports class-based context configuration * <p>This <code>ContextLoader</code> supports class-based context configuration
...@@ -46,44 +45,33 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader ...@@ -46,44 +45,33 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader
private static final Log logger = LogFactory.getLog(AnnotationConfigContextLoader.class); 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} * 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. * class names.
* *
* <p>Each class name must be the <em>fully qualified class name</em> of an * <p>Each class name must be the <em>fully qualified class name</em> of an
* annotated configuration class, component, or feature specification. The * annotated configuration class, component, or feature specification. An
* <code>AnnotationConfigApplicationContext</code> assumes the responsibility * {@link AnnotatedBeanDefinitionReader} is used to register the appropriate
* of loading the appropriate bean definitions. * 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 context the context in which the configuration classes should be registered
* @param classNames the names of configuration classes to register in the context * @param classNames the names of configuration classes to register in the context
* @throws IllegalArgumentException if the supplied context is not an instance of * @throws IllegalArgumentException if a supplied class name does not represent a class
* <code>AnnotationConfigApplicationContext</code> or if a supplied class name
* does not represent a class
* @see #createGenericApplicationContext()
*/ */
@Override @Override
protected void loadBeanDefinitions(GenericApplicationContext context, String... classNames) { 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]; Class<?>[] configClasses = new Class<?>[classNames.length];
for (int i = 0; i < classNames.length; i++) { for (int i = 0; i < classNames.length; i++) {
String className = classNames[i]; String className = classNames[i];
try { try {
configClasses[i] = (Class<?>) getClass().getClassLoader().loadClass(className); configClasses[i] = (Class<?>) context.getClassLoader().loadClass(className);
} }
catch (ClassNotFoundException e) { catch (ClassNotFoundException e) {
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
...@@ -94,7 +82,7 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader ...@@ -94,7 +82,7 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Registering configuration classes: " + ObjectUtils.nullSafeToString(configClasses)); logger.debug("Registering configuration classes: " + ObjectUtils.nullSafeToString(configClasses));
} }
((AnnotationConfigApplicationContext) context).register(configClasses); new AnnotatedBeanDefinitionReader(context).register(configClasses);
} }
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册