001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.test.context.cache; 018 019import org.springframework.context.ApplicationContext; 020import org.springframework.lang.Nullable; 021import org.springframework.test.annotation.DirtiesContext.HierarchyMode; 022import org.springframework.test.context.MergedContextConfiguration; 023 024/** 025 * {@code ContextCache} defines the SPI for caching Spring 026 * {@link ApplicationContext ApplicationContexts} within the 027 * <em>Spring TestContext Framework</em>. 028 * 029 * <p>A {@code ContextCache} maintains a cache of {@code ApplicationContexts} 030 * keyed by {@link MergedContextConfiguration} instances, potentially configured 031 * with a {@linkplain ContextCacheUtils#retrieveMaxCacheSize maximum size} and 032 * a custom eviction policy. 033 * 034 * <h3>Rationale</h3> 035 * <p>Context caching can have significant performance benefits if context 036 * initialization is complex. Although the initialization of a Spring context 037 * itself is typically very quick, some beans in a context — for example, 038 * an embedded database or a {@code LocalContainerEntityManagerFactoryBean} for 039 * working with JPA — may take several seconds to initialize. Hence it 040 * often makes sense to perform that initialization only once per test suite or 041 * JVM process. 042 * 043 * @author Sam Brannen 044 * @author Juergen Hoeller 045 * @since 4.2 046 * @see ContextCacheUtils#retrieveMaxCacheSize() 047 */ 048public interface ContextCache { 049 050 /** 051 * The name of the logging category used for reporting {@code ContextCache} 052 * statistics. 053 */ 054 String CONTEXT_CACHE_LOGGING_CATEGORY = "org.springframework.test.context.cache"; 055 056 /** 057 * The default maximum size of the context cache: {@value}. 058 * @since 4.3 059 * @see #MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME 060 */ 061 int DEFAULT_MAX_CONTEXT_CACHE_SIZE = 32; 062 063 /** 064 * System property used to configure the maximum size of the {@link ContextCache} 065 * as a positive integer. May alternatively be configured via the 066 * {@link org.springframework.core.SpringProperties} mechanism. 067 * <p>Note that implementations of {@code ContextCache} are not required to 068 * actually support a maximum cache size. Consult the documentation of the 069 * corresponding implementation for details. 070 * @since 4.3 071 * @see #DEFAULT_MAX_CONTEXT_CACHE_SIZE 072 */ 073 String MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME = "spring.test.context.cache.maxSize"; 074 075 076 /** 077 * Determine whether there is a cached context for the given key. 078 * @param key the context key (never {@code null}) 079 * @return {@code true} if the cache contains a context with the given key 080 */ 081 boolean contains(MergedContextConfiguration key); 082 083 /** 084 * Obtain a cached {@code ApplicationContext} for the given key. 085 * <p>The {@linkplain #getHitCount() hit} and {@linkplain #getMissCount() miss} 086 * counts must be updated accordingly. 087 * @param key the context key (never {@code null}) 088 * @return the corresponding {@code ApplicationContext} instance, or {@code null} 089 * if not found in the cache 090 * @see #remove 091 */ 092 @Nullable 093 ApplicationContext get(MergedContextConfiguration key); 094 095 /** 096 * Explicitly add an {@code ApplicationContext} instance to the cache 097 * under the given key, potentially honoring a custom eviction policy. 098 * @param key the context key (never {@code null}) 099 * @param context the {@code ApplicationContext} instance (never {@code null}) 100 */ 101 void put(MergedContextConfiguration key, ApplicationContext context); 102 103 /** 104 * Remove the context with the given key from the cache and explicitly 105 * {@linkplain org.springframework.context.ConfigurableApplicationContext#close() close} 106 * it if it is an instance of {@code ConfigurableApplicationContext}. 107 * <p>Generally speaking, this method should be called to properly evict 108 * a context from the cache (e.g., due to a custom eviction policy) or if 109 * the state of a singleton bean has been modified, potentially affecting 110 * future interaction with the context. 111 * <p>In addition, the semantics of the supplied {@code HierarchyMode} must 112 * be honored. See the Javadoc for {@link HierarchyMode} for details. 113 * @param key the context key; never {@code null} 114 * @param hierarchyMode the hierarchy mode; may be {@code null} if the context 115 * is not part of a hierarchy 116 */ 117 void remove(MergedContextConfiguration key, @Nullable HierarchyMode hierarchyMode); 118 119 /** 120 * Determine the number of contexts currently stored in the cache. 121 * <p>If the cache contains more than {@code Integer.MAX_VALUE} elements, 122 * this method must return {@code Integer.MAX_VALUE}. 123 */ 124 int size(); 125 126 /** 127 * Determine the number of parent contexts currently tracked within the cache. 128 */ 129 int getParentContextCount(); 130 131 /** 132 * Get the overall hit count for this cache. 133 * <p>A <em>hit</em> is any access to the cache that returns a non-null 134 * context for the queried key. 135 */ 136 int getHitCount(); 137 138 /** 139 * Get the overall miss count for this cache. 140 * <p>A <em>miss</em> is any access to the cache that returns a {@code null} 141 * context for the queried key. 142 */ 143 int getMissCount(); 144 145 /** 146 * Reset all state maintained by this cache including statistics. 147 * @see #clear() 148 * @see #clearStatistics() 149 */ 150 void reset(); 151 152 /** 153 * Clear all contexts from the cache, clearing context hierarchy information as well. 154 */ 155 void clear(); 156 157 /** 158 * Clear hit and miss count statistics for the cache (i.e., reset counters to zero). 159 */ 160 void clearStatistics(); 161 162 /** 163 * Log the statistics for this {@code ContextCache} at {@code DEBUG} level 164 * using the {@value #CONTEXT_CACHE_LOGGING_CATEGORY} logging category. 165 * <p>The following information should be logged. 166 * <ul> 167 * <li>name of the concrete {@code ContextCache} implementation</li> 168 * <li>{@linkplain #size}</li> 169 * <li>{@linkplain #getParentContextCount() parent context count}</li> 170 * <li>{@linkplain #getHitCount() hit count}</li> 171 * <li>{@linkplain #getMissCount() miss count}</li> 172 * <li>any other information useful for monitoring the state of this cache</li> 173 * </ul> 174 */ 175 void logStatistics(); 176 177}