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:
Sam Brannen
2022-08-03 16:54:32 +03:00
parent 3a890033b7
commit e3f4d810f6
11 changed files with 178 additions and 135 deletions

View File

@@ -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.""");
}
}

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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");
}

View File

@@ -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");
}

View File

@@ -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");
}