diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java b/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java index eba8207c8a2..fc8bc886617 100644 --- a/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java +++ b/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2011 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,6 @@ 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.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ConfigurableApplicationContext; @@ -48,37 +47,35 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader * Loads a Spring ApplicationContext from the supplied locations. *

Implementation details: *

- *

Subclasses must provide an appropriate implementation of - * {@link #createBeanDefinitionReader(GenericApplicationContext)}. * @return a new application context * @see org.springframework.test.context.ContextLoader#loadContext * @see GenericApplicationContext - * @see #customizeBeanFactory(DefaultListableBeanFactory) - * @see #createBeanDefinitionReader(GenericApplicationContext) - * @see BeanDefinitionReader */ public final ConfigurableApplicationContext loadContext(String... locations) throws Exception { if (logger.isDebugEnabled()) { - logger.debug("Loading ApplicationContext for locations [" + - StringUtils.arrayToCommaDelimitedString(locations) + "]."); + logger.debug(String.format("Loading ApplicationContext for locations [%s].", + StringUtils.arrayToCommaDelimitedString(locations))); } - GenericApplicationContext context = new GenericApplicationContext(); + GenericApplicationContext context = createGenericApplicationContext(); prepareContext(context); customizeBeanFactory(context.getDefaultListableBeanFactory()); - createBeanDefinitionReader(context).loadBeanDefinitions(locations); + loadBeanDefinitions(context, locations); AnnotationConfigUtils.registerAnnotationConfigProcessors(context); customizeContext(context); context.refresh(); @@ -87,7 +84,21 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader } /** - * Prepare the {@link GenericApplicationContext} created by this ContextLoader. + * Factory method for creating a new {@link GenericApplicationContext} + * to be used by this ContextLoader. + *

The default implementation returns an instance of + * {@link GenericApplicationContext}. Can be overridden in subclasses + * to return a specific subclass of GenericApplicationContext. + * @return a new GenericApplicationContext + * @since 3.1 + * @see #loadContext + */ + protected GenericApplicationContext createGenericApplicationContext() { + return new GenericApplicationContext(); + } + + /** + * Prepare the {@link GenericApplicationContext} created by this ContextLoader. * Called before bean definitions are read. *

The default implementation is empty. Can be overridden in subclasses to * customize GenericApplicationContext's standard settings. @@ -100,11 +111,10 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader } /** - * Customize the internal bean factory of the ApplicationContext created by - * this ContextLoader. + * Customize the internal bean factory of the ApplicationContext created by this ContextLoader. *

The default implementation is empty but can be overridden in subclasses * to customize DefaultListableBeanFactory's standard settings. - * @param beanFactory the bean factory created by this ContextLoader + * @param beanFactory the bean factory created by this ContextLoader * @see #loadContext * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding(boolean) * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowEagerClassLoading(boolean) @@ -115,24 +125,45 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader } /** - * Factory method for creating new {@link BeanDefinitionReader}s for + * Load bean definitions into the supplied {@link GenericApplicationContext context} + * from the specified resource locations. + *

The default implementation delegates to the {@link BeanDefinitionReader} + * returned by {@link #createBeanDefinitionReader} to + * {@link BeanDefinitionReader#loadBeanDefinitions(String) load} the + * bean definitions. + *

Subclasses must provide an appropriate implementation of + * {@link #createBeanDefinitionReader}. + * Alternatively subclasses may provide a no-op 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 + * @see #loadContext + */ + protected void loadBeanDefinitions(GenericApplicationContext context, String... locations) { + createBeanDefinitionReader(context).loadBeanDefinitions(locations); + } + + /** + * Factory method for creating a new {@link BeanDefinitionReader} for * 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 #loadContext + * @see #loadBeanDefinitions * @see BeanDefinitionReader */ protected abstract BeanDefinitionReader createBeanDefinitionReader(GenericApplicationContext context); /** - * Customize the {@link GenericApplicationContext} created by this ContextLoader - * after bean definitions have been loaded into the context but - * before the context is refreshed. + * Customize the {@link GenericApplicationContext} created by this + * ContextLoader after bean definitions have been + * loaded into the context but before the context is refreshed. *

The default implementation is empty but can be overridden in subclasses * to customize the application context. * @param context the newly created application context - * @see #loadContext(String...) + * @see #loadContext */ protected void customizeContext(GenericApplicationContext context) { } diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/support/AnnotationConfigContextLoader.java b/org.springframework.test/src/main/java/org/springframework/test/context/support/AnnotationConfigContextLoader.java index 0553d7f59a7..0336d93c42c 100644 --- a/org.springframework.test/src/main/java/org/springframework/test/context/support/AnnotationConfigContextLoader.java +++ b/org.springframework.test/src/main/java/org/springframework/test/context/support/AnnotationConfigContextLoader.java @@ -21,12 +21,10 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.context.ApplicationContext; +import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.context.support.GenericApplicationContext; -import org.springframework.util.ObjectUtils; +import org.springframework.util.Assert; /** * TODO Document AnnotationConfigContextLoader. @@ -34,99 +32,61 @@ import org.springframework.util.ObjectUtils; * @author Sam Brannen * @since 3.1 */ -public class AnnotationConfigContextLoader extends AbstractContextLoader { +public class AnnotationConfigContextLoader extends AbstractGenericContextLoader { private static final Log logger = LogFactory.getLog(AnnotationConfigContextLoader.class); /** - * TODO Document loadContext(). - * - * @see org.springframework.test.context.ContextLoader#loadContext(java.lang.String[]) + * Creates a new {@link AnnotationConfigApplicationContext}. */ - public ApplicationContext loadContext(String... locations) throws Exception { - if (logger.isDebugEnabled()) { - logger.debug("Creating an AnnotationConfigApplicationContext for " - + ObjectUtils.nullSafeToString(locations)); - } + @Override + protected GenericApplicationContext createGenericApplicationContext() { + return new AnnotationConfigApplicationContext(); + } - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - prepareContext(context); - customizeBeanFactory(context.getDefaultListableBeanFactory()); + /** + * TODO Document overridden loadBeanDefinitions(). + */ + @Override + protected void loadBeanDefinitions(GenericApplicationContext context, String... locations) { + + Assert.isInstanceOf(AnnotationConfigApplicationContext.class, context, + "context must be an instance of AnnotationConfigApplicationContext"); + + AnnotationConfigApplicationContext annotationConfigApplicationContext = (AnnotationConfigApplicationContext) context; List> configClasses = new ArrayList>(); for (String location : locations) { - final Class clazz = getClass().getClassLoader().loadClass(location); - configClasses.add(clazz); + try { + Class clazz = getClass().getClassLoader().loadClass(location); + configClasses.add(clazz); + } + catch (ClassNotFoundException e) { + throw new IllegalArgumentException(String.format( + "The supplied resource location [%s] does not represent a class.", location), e); + } } if (logger.isDebugEnabled()) { - logger.debug("Loading AnnotationConfigApplicationContext from config classes: " + configClasses); + logger.debug("Registering configuration classes: " + configClasses); } for (Class configClass : configClasses) { - context.register(configClass); + annotationConfigApplicationContext.register(configClass); } - - AnnotationConfigUtils.registerAnnotationConfigProcessors(context); - customizeContext(context); - context.refresh(); - context.registerShutdownHook(); - - return context; } /** - * Prepare the {@link GenericApplicationContext} created by this - * ContextLoader. Called before bean definitions are read. - *

- * The default implementation is empty. Can be overridden in subclasses to - * customize GenericApplicationContext's standard settings. - * - * @param context the context for which the BeanDefinitionReader should be - * created - * @see #loadContext - * @see org.springframework.context.support.GenericApplicationContext#setResourceLoader - * @see org.springframework.context.support.GenericApplicationContext#setId + * Returns null; intended as a no-op operation. */ - protected void prepareContext(GenericApplicationContext context) { - } - - /** - * Customize the internal bean factory of the ApplicationContext created by - * this ContextLoader. - *

- * The default implementation is empty but can be overridden in subclasses - * to customize DefaultListableBeanFactory's standard settings. - * - * @param beanFactory the bean factory created by this ContextLoader - * @see #loadContext - * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding(boolean) - * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowEagerClassLoading(boolean) - * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences(boolean) - * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping(boolean) - */ - protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) { - } - - /** - * Customize the {@link GenericApplicationContext} created by this - * ContextLoader after bean definitions have been loaded into the - * context but before the context is refreshed. - *

- * The default implementation is empty but can be overridden in subclasses - * to customize the application context. - * - * @param context the newly created application context - * @see #loadContext(String...) - */ - protected void customizeContext(GenericApplicationContext context) { + @Override + protected BeanDefinitionReader createBeanDefinitionReader(GenericApplicationContext context) { + return null; } /** * TODO Document overridden generateDefaultLocations(). - * - * @see org.springframework.test.context.support.AbstractContextLoader#generateDefaultLocations(java.lang.Class) */ @Override protected String[] generateDefaultLocations(Class clazz) { @@ -135,21 +95,15 @@ public class AnnotationConfigContextLoader extends AbstractContextLoader { } /** - * TODO Document modifyLocations(). - * - * @see org.springframework.test.context.support.AbstractContextLoader#modifyLocations(java.lang.Class, - * java.lang.String[]) + * Returns the supplied locations unmodified. */ @Override protected String[] modifyLocations(Class clazz, String... locations) { - // TODO Implement modifyLocations() (?). return locations; } /** - * TODO Document getResourceSuffix(). - * - * @see org.springframework.test.context.support.AbstractContextLoader#getResourceSuffix() + * Returns "Config". */ @Override protected String getResourceSuffix() { diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java index d2d8d1e00eb..605c98a877e 100644 --- a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java @@ -44,10 +44,11 @@ import org.springframework.test.context.junit4.orm.HibernateSessionFlushingTests */ @RunWith(Suite.class) // Note: the following 'multi-line' layout is for enhanced code readability. -@SuiteClasses( {// +@SuiteClasses({// StandardJUnit4FeaturesTests.class,// StandardJUnit4FeaturesSpringRunnerTests.class,// SpringJUnit47ClassRunnerRuleTests.class,// + AnnotationConfigSpringJUnit4ClassRunnerAppCtxTests.class,// ExpectedExceptionSpringRunnerTests.class,// TimedSpringRunnerTests.class,// RepeatedSpringRunnerTests.class,//