Support automatic discovery of default TELs

Prior to this commit, there was no declarative mechanism for a custom
TestExecutionListener to be registered as a default
TestExecutionListener.

This commit introduces support for discovering default
TestExecutionListener implementations via the SpringFactoriesLoader
mechanism. Specifically, the spring-test module declares all core
default TestExecutionListeners under the
org.springframework.test.context.TestExecutionListener key in its
META-INF/spring.factories properties file, and third-party frameworks
and developers can contribute to the list of default
TestExecutionListeners in the same manner.

 - AbstractTestContextBootstrapper uses the SpringFactoriesLoader to
   look up the class names of all registered default
   TestExecutionListeners and sorts the instantiated listeners using
   AnnotationAwareOrderComparator.

 - DefaultTestContextBootstrapper and WebTestContextBootstrapper now
   rely on the SpringFactoriesLoader mechanism for finding default
   TestExecutionListeners instead of hard coding fully qualified class
   names.

 - To ensure that default TestExecutionListeners are registered in the
   correct order, each can implement Ordered or declare @Order.

 - AbstractTestExecutionListener and all default TestExecutionListeners
   provided by Spring now implement Ordered with appropriate values.

 - Introduced "copy constructors" in MergedContextConfiguration and
   WebMergedContextConfiguration

 - SpringFactoriesLoader now uses AnnotationAwareOrderComparator
   instead of OrderComparator.

Issue: SPR-11466
This commit is contained in:
Sam Brannen
2014-08-14 19:28:50 +02:00
parent e142fd11e0
commit e6d16148e5
18 changed files with 227 additions and 183 deletions

View File

@@ -27,7 +27,7 @@ import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.OrderComparator;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.io.UrlResource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -48,12 +48,13 @@ import org.springframework.util.StringUtils;
*
* @author Arjen Poutsma
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.2
*/
public abstract class SpringFactoriesLoader {
/** The location to look for the factories. Can be present in multiple JAR files. */
private static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
@@ -61,7 +62,7 @@ public abstract class SpringFactoriesLoader {
/**
* Load the factory implementations of the given type from the default location,
* using the given class loader.
* <p>The returned factories are ordered in accordance with the {@link OrderComparator}.
* <p>The returned factories are ordered in accordance with the {@link AnnotationAwareOrderComparator}.
* @param factoryClass the interface or abstract class representing the factory
* @param classLoader the ClassLoader to use for loading (can be {@code null} to use the default)
*/
@@ -79,7 +80,7 @@ public abstract class SpringFactoriesLoader {
for (String factoryName : factoryNames) {
result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
}
OrderComparator.sort(result);
AnnotationAwareOrderComparator.sort(result);
return result;
}