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