Revise configurable refresh support in SmartContextLoader SPI
This commit revises 903e9f2a02 based on feedback from the Spring Boot
team.
- The original loadContext(MergedContextConfiguration) method is no
longer deprecated.
- loadContext(MergedContextConfiguration, boolean) has been replaced by
loadContextForAotProcessing(MergedContextConfiguration) which is
implemented as a `default` method that throws an
UnsupportedOperationException.
- Affected code has been refactored to adjust to these changes.
See gh-28906
This commit is contained in:
@@ -27,8 +27,8 @@ import org.springframework.lang.Nullable;
|
||||
* introduced in Spring 2.5: a {@code SmartContextLoader} can choose to process
|
||||
* resource locations, component classes, or a combination of both. Furthermore, a
|
||||
* {@code SmartContextLoader} can configure the context that it
|
||||
* {@linkplain #loadContext(MergedContextConfiguration, boolean) loads} based on
|
||||
* any properties available in the provided {@link MergedContextConfiguration}.
|
||||
* {@linkplain #loadContext(MergedContextConfiguration) loads} based on any
|
||||
* properties available in the provided {@link MergedContextConfiguration}.
|
||||
* For example, active bean definition profiles can be configured for the context
|
||||
* based on {@link MergedContextConfiguration#getActiveProfiles()}.
|
||||
*
|
||||
@@ -38,14 +38,14 @@ import org.springframework.lang.Nullable;
|
||||
* <p>Clients of a {@code SmartContextLoader} should call
|
||||
* {@link #processContextConfiguration(ContextConfigurationAttributes)
|
||||
* processContextConfiguration()} prior to calling
|
||||
* {@link #loadContext(MergedContextConfiguration, boolean) loadContext()}. This
|
||||
* gives a {@code SmartContextLoader} the opportunity to provide custom support
|
||||
* for modifying resource locations or detecting default resource locations or
|
||||
* {@link #loadContext(MergedContextConfiguration) loadContext()}. This gives a
|
||||
* {@code SmartContextLoader} the opportunity to provide custom support for
|
||||
* modifying resource locations or detecting default resource locations or
|
||||
* default configuration classes. The results of
|
||||
* {@link #processContextConfiguration(ContextConfigurationAttributes)
|
||||
* processContextConfiguration()} should be merged for all classes in the
|
||||
* hierarchy of the root test class and then supplied to
|
||||
* {@link #loadContext(MergedContextConfiguration, boolean) loadContext()}.
|
||||
* {@link #loadContext(MergedContextConfiguration) loadContext()}.
|
||||
*
|
||||
* <p>NOTE: As of Spring Framework 6.0, {@code SmartContextLoader} no longer
|
||||
* supports methods defined in the {@code ContextLoader} SPI.
|
||||
@@ -131,68 +131,36 @@ public interface SmartContextLoader extends ContextLoader {
|
||||
* @return a new application context
|
||||
* @throws Exception if context loading failed
|
||||
* @see #processContextConfiguration(ContextConfigurationAttributes)
|
||||
* @see #loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @see org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)
|
||||
* @see org.springframework.context.ConfigurableApplicationContext#getEnvironment()
|
||||
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception;
|
||||
|
||||
/**
|
||||
* Load a new {@linkplain ApplicationContext} based on the supplied
|
||||
* {@link MergedContextConfiguration}, configure the context, and return the
|
||||
* context.
|
||||
* <p>Concrete implementations should register annotation configuration
|
||||
* processors with bean factories of
|
||||
* {@linkplain ApplicationContext application contexts} loaded by this
|
||||
* {@code SmartContextLoader}. Beans will therefore automatically be
|
||||
* candidates for annotation-based dependency injection using
|
||||
* {@link org.springframework.beans.factory.annotation.Autowired @Autowired},
|
||||
* {@link jakarta.annotation.Resource @Resource}, and
|
||||
* {@link jakarta.inject.Inject @Inject}. In addition, concrete implementations
|
||||
* should perform the following actions.
|
||||
* <ul>
|
||||
* <li>Set the parent {@code ApplicationContext} if appropriate (see
|
||||
* {@link MergedContextConfiguration#getParent()}).</li>
|
||||
* <li>Set the active bean definition profiles in the context's
|
||||
* {@link org.springframework.core.env.Environment Environment} (see
|
||||
* {@link MergedContextConfiguration#getActiveProfiles()}).</li>
|
||||
* <li>Add test {@link org.springframework.core.env.PropertySource PropertySources}
|
||||
* to the {@code Environment} (see
|
||||
* {@link MergedContextConfiguration#getPropertySourceLocations()},
|
||||
* {@link MergedContextConfiguration#getPropertySourceProperties()}, and
|
||||
* {@link org.springframework.test.context.support.TestPropertySourceUtils
|
||||
* TestPropertySourceUtils}).</li>
|
||||
* <li>Invoke {@link org.springframework.context.ApplicationContextInitializer
|
||||
* ApplicationContextInitializers} (see
|
||||
* {@link MergedContextConfiguration#getContextInitializerClasses()}).</li>
|
||||
* <li>Invoke {@link ContextCustomizer ContextCustomizers} (see
|
||||
* {@link MergedContextConfiguration#getContextCustomizers()}).</li>
|
||||
* <li>If the supplied {@code refresh} flag is {@code true},
|
||||
* <p>In contrast to {@link #loadContext(MergedContextConfiguration)}, this
|
||||
* method must <strong>not</strong>
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
|
||||
* refresh} the {@code ApplicationContext} and
|
||||
* refresh} the {@code ApplicationContext} or
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
|
||||
* register a JVM shutdown hook} for it.</li>
|
||||
* </ul>
|
||||
* <p>The default implementation delegates to {@link #loadContext(MergedContextConfiguration)}
|
||||
* for backward compatibility. Concrete implementations should therefore
|
||||
* override this method in order to honor the {@code refresh} flag which is
|
||||
* required for AOT (ahead of time) processing support.
|
||||
* register a JVM shutdown hook} for it. Otherwise, this method should behave
|
||||
* identical to {@link #loadContext(MergedContextConfiguration)}.
|
||||
* <p>The default implementation throws an {@link UnsupportedOperationException}.
|
||||
* Concrete implementations must therefore override this method in order to
|
||||
* support AOT (ahead of time) processing.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @param refresh whether to refresh the {@code ApplicationContext} and register
|
||||
* a JVM shutdown hook for it
|
||||
* @return a new application context
|
||||
* @throws Exception if context loading failed
|
||||
* @since 6.0
|
||||
* @see #processContextConfiguration(ContextConfigurationAttributes)
|
||||
* @see org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)
|
||||
* @see org.springframework.context.ConfigurableApplicationContext#getEnvironment()
|
||||
* @see org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
default ApplicationContext loadContext(MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
|
||||
return loadContext(mergedConfig);
|
||||
default ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
throw new UnsupportedOperationException(
|
||||
"%s does not support loadContextForAotProcessing(MergedContextConfiguration)"
|
||||
.formatted(getClass().getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,7 +179,7 @@ public interface SmartContextLoader extends ContextLoader {
|
||||
|
||||
/**
|
||||
* {@code SmartContextLoader} does not support deprecated {@link ContextLoader} methods.
|
||||
* <p>Call {@link #loadContext(MergedContextConfiguration, boolean)} instead.
|
||||
* <p>Call {@link #loadContext(MergedContextConfiguration)} instead.
|
||||
* @throws UnsupportedOperationException in this implementation
|
||||
* @since 6.0
|
||||
*/
|
||||
@@ -220,7 +188,7 @@ public interface SmartContextLoader extends ContextLoader {
|
||||
default ApplicationContext loadContext(String... locations) throws Exception {
|
||||
throw new UnsupportedOperationException("""
|
||||
SmartContextLoader does not support the ContextLoader SPI. \
|
||||
Call loadContext(MergedContextConfiguration, boolean) instead.""");
|
||||
Call loadContext(MergedContextConfiguration) instead.""");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext
|
||||
ApplicationContext applicationContext;
|
||||
|
||||
if (contextLoader instanceof SmartContextLoader smartContextLoader) {
|
||||
applicationContext = smartContextLoader.loadContext(mergedContextConfiguration, true);
|
||||
applicationContext = smartContextLoader.loadContext(mergedContextConfiguration);
|
||||
}
|
||||
else {
|
||||
String[] locations = mergedContextConfiguration.getLocations();
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.springframework.util.Assert;
|
||||
* and enclosing class hierarchy that is annotated with
|
||||
* {@link ContextConfiguration @ContextConfiguration}, and the candidate that
|
||||
* supports the merged, processed configuration will be used to actually
|
||||
* {@linkplain #loadContext load} the context.
|
||||
* {@linkplain #loadContext(MergedContextConfiguration) load} the context.
|
||||
*
|
||||
* <p>Any reference to an <em>XML-based loader</em> can be interpreted to mean
|
||||
* a context loader that supports only XML configuration files or one that
|
||||
@@ -176,13 +176,28 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte
|
||||
}
|
||||
|
||||
/**
|
||||
* Although this method is officially deprecated, for backward compatibility
|
||||
* it delegates to {@link #loadContext(MergedContextConfiguration, boolean)},
|
||||
* supplying {@code true} for the {@code refresh} flag.
|
||||
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration, boolean)}
|
||||
* Delegates to an appropriate candidate {@code SmartContextLoader} to load
|
||||
* an {@link ApplicationContext}.
|
||||
* <p>Delegation is based on explicit knowledge of the implementations of the
|
||||
* default loaders for {@linkplain #getXmlLoader() XML configuration files and
|
||||
* Groovy scripts} and {@linkplain #getAnnotationConfigLoader() annotated classes}.
|
||||
* Specifically, the delegation algorithm is as follows:
|
||||
* <ul>
|
||||
* <li>If the resource locations in the supplied {@code MergedContextConfiguration}
|
||||
* are not empty and the annotated classes are empty,
|
||||
* the XML-based loader will load the {@code ApplicationContext}.</li>
|
||||
* <li>If the annotated classes in the supplied {@code MergedContextConfiguration}
|
||||
* are not empty and the resource locations are empty,
|
||||
* the annotation-based loader will load the {@code ApplicationContext}.</li>
|
||||
* </ul>
|
||||
* @param mergedConfig the merged context configuration to use to load the application context
|
||||
* @return a new application context
|
||||
* @throws IllegalArgumentException if the supplied merged configuration is {@code null}
|
||||
* @throws IllegalStateException if neither candidate loader is capable of loading an
|
||||
* {@code ApplicationContext} from the supplied merged context configuration
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
@@ -203,8 +218,6 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte
|
||||
* the annotation-based loader will load the {@code ApplicationContext}.</li>
|
||||
* </ul>
|
||||
* @param mergedConfig the merged context configuration to use to load the application context
|
||||
* @param refresh whether to refresh the {@code ApplicationContext} and register
|
||||
* a JVM shutdown hook for it
|
||||
* @return a new application context
|
||||
* @throws IllegalArgumentException if the supplied merged configuration is {@code null}
|
||||
* @throws IllegalStateException if neither candidate loader is capable of loading an
|
||||
@@ -212,7 +225,22 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public ApplicationContext loadContext(MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
|
||||
public ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
return loadContext(mergedConfig, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to an appropriate candidate {@code SmartContextLoader} to load
|
||||
* an {@link ApplicationContext}.
|
||||
* @param mergedConfig the merged context configuration to use to load the application context
|
||||
* @param refresh whether to refresh the {@code ApplicationContext} and register
|
||||
* a JVM shutdown hook for it
|
||||
* @return a new application context
|
||||
* @throws IllegalArgumentException if the supplied merged configuration is {@code null}
|
||||
* @throws IllegalStateException if neither candidate loader is capable of loading an
|
||||
* {@code ApplicationContext} from the supplied merged context configuration
|
||||
*/
|
||||
private ApplicationContext loadContext(MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
|
||||
Assert.notNull(mergedConfig, "MergedContextConfiguration must not be null");
|
||||
|
||||
Assert.state(!(mergedConfig.hasLocations() && mergedConfig.hasClasses()), () -> String.format(
|
||||
@@ -242,7 +270,6 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte
|
||||
name(getXmlLoader()), name(getAnnotationConfigLoader()), mergedConfig));
|
||||
}
|
||||
|
||||
|
||||
private static void delegateProcessing(SmartContextLoader loader, ContextConfigurationAttributes configAttributes) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Delegating to %s to process context configuration %s.",
|
||||
@@ -258,7 +285,7 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Delegating to %s to load context from %s.", name(loader), mergedConfig));
|
||||
}
|
||||
return loader.loadContext(mergedConfig, refresh);
|
||||
return (refresh ? loader.loadContext(mergedConfig) : loader.loadContextForAotProcessing(mergedConfig));
|
||||
}
|
||||
|
||||
private boolean supports(SmartContextLoader loader, MergedContextConfiguration mergedConfig) {
|
||||
|
||||
@@ -40,7 +40,7 @@ import org.springframework.util.StringUtils;
|
||||
* <li>If instances of concrete subclasses are invoked via the
|
||||
* {@link org.springframework.test.context.SmartContextLoader SmartContextLoader}
|
||||
* SPI, the context will be loaded from the {@link MergedContextConfiguration}
|
||||
* provided to {@link #loadContext(MergedContextConfiguration, boolean)}. In such
|
||||
* provided to {@link #loadContext(MergedContextConfiguration)}. In such
|
||||
* cases, a {@code SmartContextLoader} will decide whether to load the context
|
||||
* from <em>locations</em> or <em>annotated classes</em>.</li>
|
||||
* </ul>
|
||||
@@ -54,26 +54,15 @@ import org.springframework.util.StringUtils;
|
||||
* @author Juergen Hoeller
|
||||
* @author Phillip Webb
|
||||
* @since 2.5
|
||||
* @see #loadContext(MergedContextConfiguration, boolean)
|
||||
* @see #loadContext(MergedContextConfiguration)
|
||||
*/
|
||||
public abstract class AbstractGenericContextLoader extends AbstractContextLoader {
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(AbstractGenericContextLoader.class);
|
||||
|
||||
/**
|
||||
* Although this method is officially deprecated, for backward compatibility
|
||||
* it delegates to {@link #loadContext(MergedContextConfiguration, boolean)},
|
||||
* supplying {@code true} for the {@code refresh} flag.
|
||||
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration, boolean)}
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a Spring ApplicationContext from the supplied {@link MergedContextConfiguration}.
|
||||
* Load a {@link GenericApplicationContext} for the supplied
|
||||
* {@link MergedContextConfiguration}.
|
||||
* <p>Implementation details:
|
||||
* <ul>
|
||||
* <li>Calls {@link #validateMergedContextConfiguration(MergedContextConfiguration)}
|
||||
@@ -104,20 +93,52 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||
* <li>Calls {@link #customizeContext(ConfigurableApplicationContext, MergedContextConfiguration)} to
|
||||
* allow for customizing the context before it is refreshed.</li>
|
||||
* <li>{@link ConfigurableApplicationContext#refresh Refreshes} the
|
||||
* context and registers a JVM shutdown hook for it if the supplied the
|
||||
* {@code refresh} flag is {@code true}.</li>
|
||||
* context and registers a JVM shutdown hook for it.</li>
|
||||
* </ul>
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @return a new application context
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a {@link GenericApplicationContext} for the supplied
|
||||
* {@link MergedContextConfiguration}.
|
||||
* <p>In contrast to {@link #loadContext(MergedContextConfiguration)}, this
|
||||
* method does not
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
|
||||
* refresh} the {@code ApplicationContext} or
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
|
||||
* register a JVM shutdown hook} for it. Otherwise, this method behaves
|
||||
* identical to {@link #loadContext(MergedContextConfiguration)}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @return a new application context
|
||||
* @since 6.0
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContextForAotProcessing(
|
||||
MergedContextConfiguration mergedConfig) throws Exception {
|
||||
|
||||
return loadContext(mergedConfig, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a {@link GenericApplicationContext} for the supplied
|
||||
* {@link MergedContextConfiguration}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @param refresh whether to refresh the {@code ApplicationContext} and register
|
||||
* a JVM shutdown hook for it
|
||||
* @return a new application context
|
||||
* @since 6.0
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration, boolean)
|
||||
* @see GenericApplicationContext
|
||||
*/
|
||||
@Override
|
||||
public final ConfigurableApplicationContext loadContext(
|
||||
private final GenericApplicationContext loadContext(
|
||||
MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -185,15 +206,15 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||
* context and registers a JVM shutdown hook for it.</li>
|
||||
* </ul>
|
||||
* <p><b>Note</b>: this method does not provide a means to set active bean definition
|
||||
* profiles for the loaded context. See {@link #loadContext(MergedContextConfiguration, boolean)}
|
||||
* profiles for the loaded context. See {@link #loadContext(MergedContextConfiguration)}
|
||||
* and {@link AbstractContextLoader#prepareContext(ConfigurableApplicationContext, MergedContextConfiguration)}
|
||||
* for an alternative.
|
||||
* @return a new application context
|
||||
* @since 2.5
|
||||
* @see org.springframework.test.context.ContextLoader#loadContext
|
||||
* @see GenericApplicationContext
|
||||
* @see #loadContext(MergedContextConfiguration, boolean)
|
||||
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration, boolean)}
|
||||
* @see #loadContext(MergedContextConfiguration)
|
||||
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContextForAotProcessing(MergedContextConfiguration)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
@@ -238,8 +259,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||
* customize {@code GenericApplicationContext}'s standard settings.
|
||||
* @param context the context that should be prepared
|
||||
* @since 2.5
|
||||
* @see #loadContext(MergedContextConfiguration, boolean)
|
||||
* @see #loadContext(String...)
|
||||
* @see #loadContext(MergedContextConfiguration)
|
||||
* @see GenericApplicationContext#setAllowBeanDefinitionOverriding
|
||||
* @see GenericApplicationContext#setResourceLoader
|
||||
* @see GenericApplicationContext#setId
|
||||
@@ -255,8 +275,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||
* to customize {@code DefaultListableBeanFactory}'s standard settings.
|
||||
* @param beanFactory the bean factory created by this {@code ContextLoader}
|
||||
* @since 2.5
|
||||
* @see #loadContext(MergedContextConfiguration, boolean)
|
||||
* @see #loadContext(String...)
|
||||
* @see #loadContext(MergedContextConfiguration)
|
||||
* @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
|
||||
* @see DefaultListableBeanFactory#setAllowEagerClassLoading
|
||||
* @see DefaultListableBeanFactory#setAllowCircularReferences
|
||||
@@ -280,7 +299,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||
* @param context the context into which the bean definitions should be loaded
|
||||
* @param mergedConfig the merged context configuration
|
||||
* @since 3.1
|
||||
* @see #loadContext(MergedContextConfiguration, boolean)
|
||||
* @see #loadContext(MergedContextConfiguration)
|
||||
*/
|
||||
protected void loadBeanDefinitions(GenericApplicationContext context, MergedContextConfiguration mergedConfig) {
|
||||
createBeanDefinitionReader(context).loadBeanDefinitions(mergedConfig.getLocations());
|
||||
@@ -293,7 +312,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||
* should be created
|
||||
* @return a {@code BeanDefinitionReader} for the supplied context
|
||||
* @since 2.5
|
||||
* @see #loadContext(String...)
|
||||
* @see #loadContext(MergedContextConfiguration)
|
||||
* @see #loadBeanDefinitions
|
||||
* @see BeanDefinitionReader
|
||||
*/
|
||||
@@ -307,8 +326,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||
* to customize the application context.
|
||||
* @param context the newly created application context
|
||||
* @since 2.5
|
||||
* @see #loadContext(MergedContextConfiguration, boolean)
|
||||
* @see #loadContext(String...)
|
||||
* @see #loadContext(MergedContextConfiguration)
|
||||
* @see #customizeContext(ConfigurableApplicationContext, MergedContextConfiguration)
|
||||
*/
|
||||
protected void customizeContext(GenericApplicationContext context) {
|
||||
|
||||
@@ -65,19 +65,7 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
|
||||
// SmartContextLoader
|
||||
|
||||
/**
|
||||
* Although this method is officially deprecated, for backward compatibility
|
||||
* it delegates to {@link #loadContext(MergedContextConfiguration, boolean)},
|
||||
* supplying {@code true} for the {@code refresh} flag.
|
||||
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration, boolean)}
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a Spring {@link WebApplicationContext} from the supplied
|
||||
* Load a {@link GenericWebApplicationContext} for the supplied
|
||||
* {@link MergedContextConfiguration}.
|
||||
* <p>Implementation details:
|
||||
* <ul>
|
||||
@@ -108,15 +96,52 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
|
||||
* </ul>
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @return a new web application context
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
|
||||
* @see GenericWebApplicationContext
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a {@link GenericWebApplicationContext} for the supplied
|
||||
* {@link MergedContextConfiguration}.
|
||||
* <p>In contrast to {@link #loadContext(MergedContextConfiguration)}, this
|
||||
* method does not
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
|
||||
* refresh} the {@code ApplicationContext} or
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
|
||||
* register a JVM shutdown hook} for it. Otherwise, this method behaves
|
||||
* identical to {@link #loadContext(MergedContextConfiguration)}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @return a new web application context
|
||||
* @since 6.0
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @see GenericWebApplicationContext
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContextForAotProcessing(
|
||||
MergedContextConfiguration mergedConfig) throws Exception {
|
||||
|
||||
return loadContext(mergedConfig, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a {@link GenericWebApplicationContext} for the supplied
|
||||
* {@link MergedContextConfiguration}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @param refresh whether to refresh the {@code ApplicationContext} and register
|
||||
* a JVM shutdown hook for it
|
||||
* @return a new web application context
|
||||
* @since 6.0
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration, boolean)
|
||||
* @see GenericWebApplicationContext
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
*/
|
||||
@Override
|
||||
public final ConfigurableApplicationContext loadContext(
|
||||
private final GenericWebApplicationContext loadContext(
|
||||
MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
|
||||
|
||||
Assert.isTrue(mergedConfig instanceof WebMergedContextConfiguration,
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
|
||||
@@ -48,7 +49,7 @@ class AnnotationConfigContextLoaderTests {
|
||||
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(getClass(),
|
||||
new String[] { "config.xml" }, EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, contextLoader);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> contextLoader.loadContext(mergedConfig, true))
|
||||
.isThrownBy(() -> contextLoader.loadContext(mergedConfig))
|
||||
.withMessageContaining("does not support resource locations");
|
||||
}
|
||||
|
||||
@@ -56,30 +57,34 @@ class AnnotationConfigContextLoaderTests {
|
||||
* @since 6.0
|
||||
*/
|
||||
@Test
|
||||
void loadContextHonorsRefreshTrue() throws Exception {
|
||||
void loadContextRefreshesContext() throws Exception {
|
||||
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
|
||||
AnnotatedFooConfigInnerClassTestCase.class, EMPTY_STRING_ARRAY,
|
||||
new Class<?>[] {AnnotatedFooConfigInnerClassTestCase.FooConfig.class},
|
||||
EMPTY_STRING_ARRAY, contextLoader);
|
||||
ConfigurableApplicationContext context = contextLoader.loadContext(mergedConfig, true);
|
||||
assertThat(context).isNotNull();
|
||||
assertThat(context.isActive()).as("ApplicationContext is active").isTrue();
|
||||
ApplicationContext context = contextLoader.loadContext(mergedConfig);
|
||||
assertThat(context).isInstanceOf(ConfigurableApplicationContext.class);
|
||||
ConfigurableApplicationContext cac = (ConfigurableApplicationContext) context;
|
||||
assertThat(cac.isActive()).as("ApplicationContext is active").isTrue();
|
||||
assertThat(context.getBean(String.class)).isEqualTo("foo");
|
||||
cac.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Test
|
||||
void loadContextHonorsRefreshFalse() throws Exception {
|
||||
void loadContextForAotProcessingDoesNotRefreshContext() throws Exception {
|
||||
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
|
||||
AnnotatedFooConfigInnerClassTestCase.class, EMPTY_STRING_ARRAY,
|
||||
new Class<?>[] {AnnotatedFooConfigInnerClassTestCase.FooConfig.class},
|
||||
EMPTY_STRING_ARRAY, contextLoader);
|
||||
ConfigurableApplicationContext context = contextLoader.loadContext(mergedConfig, false);
|
||||
assertThat(context).isNotNull();
|
||||
assertThat(context.isActive()).as("ApplicationContext is active").isFalse();
|
||||
ApplicationContext context = contextLoader.loadContextForAotProcessing(mergedConfig);
|
||||
assertThat(context).isInstanceOf(ConfigurableApplicationContext.class);
|
||||
ConfigurableApplicationContext cac = (ConfigurableApplicationContext) context;
|
||||
assertThat(cac.isActive()).as("ApplicationContext is active").isFalse();
|
||||
assertThat(Arrays.stream(context.getBeanDefinitionNames())).anyMatch(name -> name.contains("FooConfig"));
|
||||
cac.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -53,7 +53,7 @@ class CustomizedGenericXmlContextLoaderTests {
|
||||
|
||||
MergedContextConfiguration mergedConfig =
|
||||
new MergedContextConfiguration(getClass(), null, null, null, null);
|
||||
customLoader.loadContext(mergedConfig, true);
|
||||
customLoader.loadContext(mergedConfig);
|
||||
|
||||
assertThat(customizeInvoked).as("customizeContext() should have been invoked").isTrue();
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ class DelegatingSmartContextLoaderTests {
|
||||
|
||||
@Test
|
||||
void loadContextWithNullConfig() throws Exception {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> loader.loadContext(null, true));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> loader.loadContext((MergedContextConfiguration) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,7 +108,7 @@ class DelegatingSmartContextLoaderTests {
|
||||
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
|
||||
getClass(), EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, loader);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig, true))
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig))
|
||||
.withMessageStartingWith("Neither")
|
||||
.withMessageContaining("was able to load an ApplicationContext from");
|
||||
}
|
||||
@@ -121,7 +121,7 @@ class DelegatingSmartContextLoaderTests {
|
||||
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(getClass(),
|
||||
new String[] {"test.xml"}, new Class<?>[] {getClass()}, EMPTY_STRING_ARRAY, loader);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig, true))
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig))
|
||||
.withMessageStartingWith("Neither")
|
||||
.withMessageContaining("declare either 'locations' or 'classes' but not both.");
|
||||
}
|
||||
@@ -147,7 +147,7 @@ class DelegatingSmartContextLoaderTests {
|
||||
private void assertApplicationContextLoadsAndContainsFooString(MergedContextConfiguration mergedConfig)
|
||||
throws Exception {
|
||||
|
||||
ApplicationContext applicationContext = loader.loadContext(mergedConfig, true);
|
||||
ApplicationContext applicationContext = loader.loadContext(mergedConfig);
|
||||
assertThat(applicationContext).isInstanceOf(ConfigurableApplicationContext.class);
|
||||
assertThat(applicationContext.getBean(String.class)).isEqualTo("foo");
|
||||
ConfigurableApplicationContext cac = (ConfigurableApplicationContext) applicationContext;
|
||||
@@ -164,7 +164,7 @@ class DelegatingSmartContextLoaderTests {
|
||||
new String[] {"classpath:/org/springframework/test/context/support/DelegatingSmartContextLoaderTests$XmlTestCase-context.xml"},
|
||||
EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, loader);
|
||||
|
||||
assertApplicationContextLoadsWithoutRefresh(mergedConfig, "foo");
|
||||
assertApplicationContextLoadsForAotProcessing(mergedConfig, "foo");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,13 +175,13 @@ class DelegatingSmartContextLoaderTests {
|
||||
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(ConfigClassTestCase.class,
|
||||
EMPTY_STRING_ARRAY, new Class<?>[] {ConfigClassTestCase.Config.class}, EMPTY_STRING_ARRAY, loader);
|
||||
|
||||
assertApplicationContextLoadsWithoutRefresh(mergedConfig, "ConfigClassTestCase.Config");
|
||||
assertApplicationContextLoadsForAotProcessing(mergedConfig, "ConfigClassTestCase.Config");
|
||||
}
|
||||
|
||||
private void assertApplicationContextLoadsWithoutRefresh(MergedContextConfiguration mergedConfig,
|
||||
private void assertApplicationContextLoadsForAotProcessing(MergedContextConfiguration mergedConfig,
|
||||
String expectedBeanDefName) throws Exception {
|
||||
|
||||
ApplicationContext context = loader.loadContext(mergedConfig, false);
|
||||
ApplicationContext context = loader.loadContextForAotProcessing(mergedConfig);
|
||||
assertThat(context).isInstanceOf(ConfigurableApplicationContext.class);
|
||||
ConfigurableApplicationContext cac = (ConfigurableApplicationContext) context;
|
||||
assertThat(cac.isActive()).as("ApplicationContext is active").isFalse();
|
||||
|
||||
@@ -40,7 +40,7 @@ class GenericXmlContextLoaderTests {
|
||||
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||
new Class<?>[] { getClass() }, EMPTY_STRING_ARRAY, loader);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig, true))
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig))
|
||||
.withMessageContaining("does not support annotated classes");
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class AnnotationConfigWebContextLoaderTests {
|
||||
new String[] { "config.xml" }, EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY,
|
||||
EMPTY_STRING_ARRAY, "resource/path", loader, null, null);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig, true))
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig))
|
||||
.withMessageContaining("does not support resource locations");
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class GenericXmlWebContextLoaderTests {
|
||||
new Class<?>[] { getClass() }, null, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY,
|
||||
"resource/path", loader, null, null);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig, true))
|
||||
.isThrownBy(() -> loader.loadContext(mergedConfig))
|
||||
.withMessageContaining("does not support annotated classes");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user