Skip to content

Commit 9e6a5ae

Browse files
committed
Merge pull request #780 from sbrannen/SPR-12683
Improve extensibility of TestContext bootstrapping & context caching These commits include numerous refactorings and enhancements to the bootstrapping and context caching mechanisms in the Spring TestContext Framework. Issue: SPR-12683
2 parents 0cb22fc + 129488c commit 9e6a5ae

18 files changed

+666
-331
lines changed

spring-test/src/main/java/org/springframework/test/context/BootstrapContext.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,14 +28,15 @@
2828
public interface BootstrapContext {
2929

3030
/**
31-
* Get the {@link Class test class} for this bootstrap context.
31+
* Get the {@linkplain Class test class} for this bootstrap context.
3232
* @return the test class (never {@code null})
3333
*/
3434
Class<?> getTestClass();
3535

3636
/**
3737
* Get the {@link CacheAwareContextLoaderDelegate} to use for transparent
38-
* interaction with the <em>context cache</em>.
38+
* interaction with the {@code ContextCache}.
39+
* @return the context loader delegate (never {@code null})
3940
*/
4041
CacheAwareContextLoaderDelegate getCacheAwareContextLoaderDelegate();
4142

spring-test/src/main/java/org/springframework/test/context/BootstrapUtils.java

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.test.context;
1818

19+
import java.lang.reflect.Constructor;
20+
1921
import org.apache.commons.logging.Log;
2022
import org.apache.commons.logging.LogFactory;
2123

@@ -36,6 +38,10 @@
3638
*/
3739
abstract class BootstrapUtils {
3840

41+
private static final String DEFAULT_BOOTSTRAP_CONTEXT_CLASS_NAME = "org.springframework.test.context.support.DefaultBootstrapContext";
42+
43+
private static final String DEFAULT_CACHE_AWARE_CONTEXT_LOADER_DELEGATE_CLASS_NAME = "org.springframework.test.context.support.DefaultCacheAwareContextLoaderDelegate";
44+
3945
private static final String DEFAULT_TEST_CONTEXT_BOOTSTRAPPER_CLASS_NAME = "org.springframework.test.context.support.DefaultTestContextBootstrapper";
4046

4147
private static final Log logger = LogFactory.getLog(BootstrapUtils.class);
@@ -45,6 +51,55 @@ private BootstrapUtils() {
4551
/* no-op */
4652
}
4753

54+
/**
55+
* Create the {@code BootstrapContext} for the specified {@linkplain Class test class}.
56+
*
57+
* <p>Uses reflection to create a {@link org.springframework.test.context.support.DefaultBootstrapContext}
58+
* that uses a {@link org.springframework.test.context.support.DefaultCacheAwareContextLoaderDelegate}.
59+
*
60+
* @param testClass the test class for which the bootstrap context should be created
61+
* @return a new {@code BootstrapContext}; never {@code null}
62+
*/
63+
@SuppressWarnings("unchecked")
64+
static BootstrapContext createBootstrapContext(Class<?> testClass) {
65+
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate = createCacheAwareContextLoaderDelegate();
66+
67+
Class<? extends BootstrapContext> clazz = null;
68+
try {
69+
clazz = (Class<? extends BootstrapContext>) ClassUtils.forName(DEFAULT_BOOTSTRAP_CONTEXT_CLASS_NAME,
70+
BootstrapUtils.class.getClassLoader());
71+
72+
Constructor<? extends BootstrapContext> constructor = clazz.getConstructor(Class.class,
73+
CacheAwareContextLoaderDelegate.class);
74+
75+
if (logger.isDebugEnabled()) {
76+
logger.debug(String.format("Instantiating BootstrapContext using constructor [%s]", constructor));
77+
}
78+
return instantiateClass(constructor, testClass, cacheAwareContextLoaderDelegate);
79+
}
80+
catch (Throwable t) {
81+
throw new IllegalStateException("Could not load BootstrapContext [" + clazz + "]", t);
82+
}
83+
}
84+
85+
@SuppressWarnings("unchecked")
86+
private static CacheAwareContextLoaderDelegate createCacheAwareContextLoaderDelegate() {
87+
Class<? extends CacheAwareContextLoaderDelegate> clazz = null;
88+
try {
89+
clazz = (Class<? extends CacheAwareContextLoaderDelegate>) ClassUtils.forName(
90+
DEFAULT_CACHE_AWARE_CONTEXT_LOADER_DELEGATE_CLASS_NAME, BootstrapUtils.class.getClassLoader());
91+
92+
if (logger.isDebugEnabled()) {
93+
logger.debug(String.format("Instantiating CacheAwareContextLoaderDelegate from class [%s]",
94+
clazz.getName()));
95+
}
96+
return instantiateClass(clazz, CacheAwareContextLoaderDelegate.class);
97+
}
98+
catch (Throwable t) {
99+
throw new IllegalStateException("Could not load CacheAwareContextLoaderDelegate [" + clazz + "]", t);
100+
}
101+
}
102+
48103
/**
49104
* Resolve the {@link TestContextBootstrapper} type for the test class in the
50105
* supplied {@link BootstrapContext}, instantiate it, and provide it a reference

spring-test/src/main/java/org/springframework/test/context/CacheAwareContextLoaderDelegate.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
2323
/**
2424
* A {@code CacheAwareContextLoaderDelegate} is responsible for {@linkplain
2525
* #loadContext loading} and {@linkplain #closeContext closing} application
26-
* contexts, interacting transparently with a <em>context cache</em> behind
26+
* contexts, interacting transparently with a {@link ContextCache} behind
2727
* the scenes.
2828
*
2929
* <p>Note: {@code CacheAwareContextLoaderDelegate} does not extend the
@@ -38,8 +38,10 @@ public interface CacheAwareContextLoaderDelegate {
3838
* Load the {@linkplain ApplicationContext application context} for the supplied
3939
* {@link MergedContextConfiguration} by delegating to the {@link ContextLoader}
4040
* configured in the given {@code MergedContextConfiguration}.
41-
* <p>If the context is present in the <em>context cache</em> it will simply
41+
* <p>If the context is present in the {@code ContextCache} it will simply
4242
* be returned; otherwise, it will be loaded, stored in the cache, and returned.
43+
* <p>The cache statistics should be logged by invoking
44+
* {@link ContextCache#logStatistics()}.
4345
* @param mergedContextConfiguration the merged context configuration to use
4446
* to load the application context; never {@code null}
4547
* @return the application context
@@ -50,7 +52,7 @@ public interface CacheAwareContextLoaderDelegate {
5052

5153
/**
5254
* Remove the {@linkplain ApplicationContext application context} for the
53-
* supplied {@link MergedContextConfiguration} from the <em>context cache</em>
55+
* supplied {@link MergedContextConfiguration} from the {@code ContextCache}
5456
* and {@linkplain ConfigurableApplicationContext#close() close} it if it is
5557
* an instance of {@link ConfigurableApplicationContext}.
5658
* <p>The semantics of the supplied {@code HierarchyMode} must be honored when

0 commit comments

Comments
 (0)