/* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.test.context.cache; import org.springframework.context.ApplicationContext; import org.springframework.test.annotation.DirtiesContext.HierarchyMode; import org.springframework.test.context.MergedContextConfiguration; /** * {@code ContextCache} defines the SPI for caching Spring * {@link ApplicationContext ApplicationContexts} within the * <em>Spring TestContext Framework</em>. * * <p>A {@code ContextCache} maintains a cache of {@code ApplicationContexts} * keyed by {@link MergedContextConfiguration} instances, potentially configured * with a {@linkplain ContextCacheUtils#retrieveMaxCacheSize maximum size} and * a custom eviction policy. * * <h3>Rationale</h3> * <p>Context caching can have significant performance benefits if context * initialization is complex. Although the initialization of a Spring context * itself is typically very quick, some beans in a context — for example, * an embedded database or a {@code LocalContainerEntityManagerFactoryBean} for * working with JPA — may take several seconds to initialize. Hence it * often makes sense to perform that initialization only once per test suite or * JVM process. * * @author Sam Brannen * @author Juergen Hoeller * @since 4.2 * @see ContextCacheUtils#retrieveMaxCacheSize() */ public interface ContextCache { /** * The name of the logging category used for reporting {@code ContextCache} * statistics. */ String CONTEXT_CACHE_LOGGING_CATEGORY = "org.springframework.test.context.cache"; /** * The default maximum size of the context cache: {@value #DEFAULT_MAX_CONTEXT_CACHE_SIZE}. * @since 4.3 * @see #MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME */ int DEFAULT_MAX_CONTEXT_CACHE_SIZE = 32; /** * System property used to configure the maximum size of the {@link ContextCache} * as a positive integer. May alternatively be configured via the * {@link org.springframework.core.SpringProperties} mechanism. * <p>Note that implementations of {@code ContextCache} are not required to * actually support a maximum cache size. Consult the documentation of the * corresponding implementation for details. * @since 4.3 * @see #DEFAULT_MAX_CONTEXT_CACHE_SIZE */ String MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME = "spring.test.context.cache.maxSize"; /** * Determine whether there is a cached context for the given key. * @param key the context key (never {@code null}) * @return {@code true} if the cache contains a context with the given key */ boolean contains(MergedContextConfiguration key); /** * Obtain a cached {@code ApplicationContext} for the given key. * <p>The {@linkplain #getHitCount() hit} and {@linkplain #getMissCount() miss} * counts must be updated accordingly. * @param key the context key (never {@code null}) * @return the corresponding {@code ApplicationContext} instance, or {@code null} * if not found in the cache * @see #remove */ ApplicationContext get(MergedContextConfiguration key); /** * Explicitly add an {@code ApplicationContext} instance to the cache * under the given key, potentially honoring a custom eviction policy. * @param key the context key (never {@code null}) * @param context the {@code ApplicationContext} instance (never {@code null}) */ void put(MergedContextConfiguration key, ApplicationContext context); /** * Remove the context with the given key from the cache and explicitly * {@linkplain org.springframework.context.ConfigurableApplicationContext#close() close} * it if it is an instance of {@code ConfigurableApplicationContext}. * <p>Generally speaking, this method should be called to properly evict * a context from the cache (e.g., due to a custom eviction policy) or if * the state of a singleton bean has been modified, potentially affecting * future interaction with the context. * <p>In addition, the semantics of the supplied {@code HierarchyMode} must * be honored. See the Javadoc for {@link HierarchyMode} for details. * @param key the context key; never {@code null} * @param hierarchyMode the hierarchy mode; may be {@code null} if the context * is not part of a hierarchy */ void remove(MergedContextConfiguration key, HierarchyMode hierarchyMode); /** * Determine the number of contexts currently stored in the cache. * <p>If the cache contains more than {@code Integer.MAX_VALUE} elements, * this method must return {@code Integer.MAX_VALUE}. */ int size(); /** * Determine the number of parent contexts currently tracked within the cache. */ int getParentContextCount(); /** * Get the overall hit count for this cache. * <p>A <em>hit</em> is any access to the cache that returns a non-null * context for the queried key. */ int getHitCount(); /** * Get the overall miss count for this cache. * <p>A <em>miss</em> is any access to the cache that returns a {@code null} * context for the queried key. */ int getMissCount(); /** * Reset all state maintained by this cache including statistics. * @see #clear() * @see #clearStatistics() */ void reset(); /** * Clear all contexts from the cache, clearing context hierarchy information as well. */ void clear(); /** * Clear hit and miss count statistics for the cache (i.e., reset counters to zero). */ void clearStatistics(); /** * Log the statistics for this {@code ContextCache} at {@code DEBUG} level * using the {@value #CONTEXT_CACHE_LOGGING_CATEGORY} logging category. * <p>The following information should be logged. * <ul> * <li>name of the concrete {@code ContextCache} implementation</li> * <li>{@linkplain #size}</li> * <li>{@linkplain #getParentContextCount() parent context count}</li> * <li>{@linkplain #getHitCount() hit count}</li> * <li>{@linkplain #getMissCount() miss count}</li> * <li>any other information useful for monitoring the state of this cache</li> * </ul> */ void logStatistics(); }