Improve documentation of SmartContextLoader contracts

This commit is contained in:
Sam Brannen 2022-08-02 13:48:53 +03:00
parent ee33aa6117
commit 72548f7611
1 changed files with 48 additions and 34 deletions

View File

@ -20,15 +20,17 @@ import org.springframework.context.ApplicationContext;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
/** /**
* Strategy interface for loading an {@link ApplicationContext application context} * Strategy interface for loading an {@link ApplicationContext} for an integration
* for an integration test managed by the Spring TestContext Framework. * test managed by the Spring TestContext Framework.
* *
* <p>The {@code SmartContextLoader} SPI supersedes the {@link ContextLoader} SPI * <p>The {@code SmartContextLoader} SPI supersedes the {@link ContextLoader} SPI
* introduced in Spring 2.5: a {@code SmartContextLoader} can choose to process * introduced in Spring 2.5: a {@code SmartContextLoader} can choose to process
* either resource locations or annotated classes. Furthermore, a * resource locations, annotated classes, or a combination of both. Furthermore, a
* {@code SmartContextLoader} can set active bean definition profiles in the * {@code SmartContextLoader} can configure the context that it
* context that it loads (see {@link MergedContextConfiguration#getActiveProfiles()} * {@linkplain #loadContext(MergedContextConfiguration) loads} based on any
* and {@link #loadContext(MergedContextConfiguration)}). * properties available in the provided {@link MergedContextConfiguration}. For
* example, active bean definition profiles can be configured for the context
* based on {@link MergedContextConfiguration#getActiveProfiles()}.
* *
* <p>See the Javadoc for {@link ContextConfiguration @ContextConfiguration} * <p>See the Javadoc for {@link ContextConfiguration @ContextConfiguration}
* for a definition of <em>annotated class</em>. * for a definition of <em>annotated class</em>.
@ -45,11 +47,8 @@ import org.springframework.lang.Nullable;
* hierarchy of the root test class and then supplied to * hierarchy of the root test class and then supplied to
* {@link #loadContext(MergedContextConfiguration) loadContext()}. * {@link #loadContext(MergedContextConfiguration) loadContext()}.
* *
* <p>Even though {@code SmartContextLoader} extends {@code ContextLoader}, * <p>NOTE: As of Spring Framework 6.0, {@code SmartContextLoader} no longer
* clients should favor {@code SmartContextLoader}-specific methods over those * supports methods defined in the {@code ContextLoader} SPI.
* defined in {@code ContextLoader}, particularly because a
* {@code SmartContextLoader} may choose not to support methods defined in the
* {@code ContextLoader} SPI.
* *
* <p>Concrete implementations must provide a {@code public} no-args constructor. * <p>Concrete implementations must provide a {@code public} no-args constructor.
* *
@ -58,43 +57,45 @@ import org.springframework.lang.Nullable;
* <li>{@link org.springframework.test.context.support.DelegatingSmartContextLoader DelegatingSmartContextLoader}</li> * <li>{@link org.springframework.test.context.support.DelegatingSmartContextLoader DelegatingSmartContextLoader}</li>
* <li>{@link org.springframework.test.context.support.AnnotationConfigContextLoader AnnotationConfigContextLoader}</li> * <li>{@link org.springframework.test.context.support.AnnotationConfigContextLoader AnnotationConfigContextLoader}</li>
* <li>{@link org.springframework.test.context.support.GenericXmlContextLoader GenericXmlContextLoader}</li> * <li>{@link org.springframework.test.context.support.GenericXmlContextLoader GenericXmlContextLoader}</li>
* <li>{@link org.springframework.test.context.support.GenericGroovyXmlContextLoader GenericGroovyXmlContextLoader}</li>
* <li>{@link org.springframework.test.context.web.WebDelegatingSmartContextLoader WebDelegatingSmartContextLoader}</li> * <li>{@link org.springframework.test.context.web.WebDelegatingSmartContextLoader WebDelegatingSmartContextLoader}</li>
* <li>{@link org.springframework.test.context.web.AnnotationConfigWebContextLoader AnnotationConfigWebContextLoader}</li> * <li>{@link org.springframework.test.context.web.AnnotationConfigWebContextLoader AnnotationConfigWebContextLoader}</li>
* <li>{@link org.springframework.test.context.web.GenericXmlWebContextLoader GenericXmlWebContextLoader}</li> * <li>{@link org.springframework.test.context.web.GenericXmlWebContextLoader GenericXmlWebContextLoader}</li>
* <li>{@link org.springframework.test.context.web.GenericGroovyXmlWebContextLoader GenericGroovyXmlWebContextLoader}</li>
* </ul> * </ul>
* *
* @author Sam Brannen * @author Sam Brannen
* @since 3.1 * @since 3.1
* @see ContextConfiguration * @see ContextConfiguration
* @see ActiveProfiles * @see ActiveProfiles
* @see TestPropertySource
* @see ContextConfigurationAttributes * @see ContextConfigurationAttributes
* @see MergedContextConfiguration * @see MergedContextConfiguration
*/ */
public interface SmartContextLoader extends ContextLoader { public interface SmartContextLoader extends ContextLoader {
/** /**
* Processes the {@link ContextConfigurationAttributes} for a given test class. * Process the {@link ContextConfigurationAttributes} for a given test class.
* <p>Concrete implementations may choose to <em>modify</em> the {@code locations} * <p>Concrete implementations may choose to <em>modify</em> the {@code locations}
* or {@code classes} in the supplied {@link ContextConfigurationAttributes}, * or {@code classes} in the supplied {@code ContextConfigurationAttributes},
* <em>generate</em> default configuration locations, or <em>detect</em> * <em>generate</em> default configuration locations, or <em>detect</em>
* default configuration classes if the supplied values are {@code null} * default configuration classes if the supplied values are {@code null}
* or empty. * or empty.
* <p><b>Note</b>: in contrast to a standard {@code ContextLoader}, a * <p><b>Note</b>: a {@code SmartContextLoader} must <em>preemptively</em>
* {@code SmartContextLoader} <b>must</b> <em>preemptively</em> verify that * verify that a generated or detected default actually exists before setting
* a generated or detected default actually exists before setting the corresponding * the corresponding {@code locations} or {@code classes} property in the
* {@code locations} or {@code classes} property in the supplied * supplied {@code ContextConfigurationAttributes}. Consequently, leaving the
* {@link ContextConfigurationAttributes}. Consequently, leaving the * {@code locations} or {@code classes} property empty signals that this
* {@code locations} or {@code classes} property empty signals that * {@code SmartContextLoader} was not able to generate or detect defaults.
* this {@code SmartContextLoader} was not able to generate or detect defaults.
* @param configAttributes the context configuration attributes to process * @param configAttributes the context configuration attributes to process
*/ */
void processContextConfiguration(ContextConfigurationAttributes configAttributes); void processContextConfiguration(ContextConfigurationAttributes configAttributes);
/** /**
* Loads a new {@link ApplicationContext context} based on the supplied * Load a new {@linkplain ApplicationContext context} based on the supplied
* {@link MergedContextConfiguration merged context configuration}, * {@link MergedContextConfiguration merged context configuration},
* configures the context, and finally returns the context in a fully * configure the context, and return the context in a fully <em>refreshed</em>
* <em>refreshed</em> state. * state.
* <p>Concrete implementations should register annotation configuration * <p>Concrete implementations should register annotation configuration
* processors with bean factories of * processors with bean factories of
* {@link ApplicationContext application contexts} loaded by this * {@link ApplicationContext application contexts} loaded by this
@ -103,22 +104,35 @@ public interface SmartContextLoader extends ContextLoader {
* {@link org.springframework.beans.factory.annotation.Autowired @Autowired}, * {@link org.springframework.beans.factory.annotation.Autowired @Autowired},
* {@link jakarta.annotation.Resource @Resource}, and * {@link jakarta.annotation.Resource @Resource}, and
* {@link jakarta.inject.Inject @Inject}. In addition, concrete implementations * {@link jakarta.inject.Inject @Inject}. In addition, concrete implementations
* should set the active bean definition profiles in the context's * should perform the following actions.
* {@link org.springframework.core.env.Environment Environment}. * <ul>
* <p>Any {@code ApplicationContext} loaded by a * <li>Set the parent {@code ApplicationContext} if appropriate (see
* {@code SmartContextLoader} <strong>must</strong> register a JVM * {@link MergedContextConfiguration#getParent()}).</li>
* shutdown hook for itself. Unless the context gets closed early, all context * <li>Set the active bean definition profiles in the context's
* instances will be automatically closed on JVM shutdown. This allows for * {@link org.springframework.core.env.Environment Environment} (see
* freeing of external resources held by beans within the context (e.g., * {@link MergedContextConfiguration#getActiveProfiles()}).</li>
* temporary files). * <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>Register a JVM shutdown hook for the {@link ApplicationContext}. Unless
* the context gets closed early, all context instances will be automatically
* closed on JVM shutdown. This allows for freeing of external resources held
* by beans within the context &mdash; for example, temporary files.</li>
* </ul>
* @param mergedConfig the merged context configuration to use to load the * @param mergedConfig the merged context configuration to use to load the
* application context * application context
* @return a new application context * @return a new application context
* @throws Exception if context loading failed * @throws Exception if context loading failed
* @see #processContextConfiguration(ContextConfigurationAttributes) * @see #processContextConfiguration(ContextConfigurationAttributes)
* @see org.springframework.context.annotation.AnnotationConfigUtils * @see org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)
* #registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)
* @see MergedContextConfiguration#getActiveProfiles()
* @see org.springframework.context.ConfigurableApplicationContext#getEnvironment() * @see org.springframework.context.ConfigurableApplicationContext#getEnvironment()
*/ */
ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception; ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception;