核心:使用CacheManager[ConcurrentMapCacheManager]按照名字得到Cache[ConcurrentMapCache]组件
key使用keyGenerator生成的,默认是SimpleKeyGenerator
@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,如果没有就运行犯法并将结果放入缓存,以后再来调用就可以直接使用缓存中的数据.
- 自动配置类
@Import({CacheAutoConfiguration.CacheConfigurationImportSelector.class, CacheAutoConfiguration.CacheManagerEntityManagerFactoryDependsOnPostProcessor.class})
public class CacheAutoConfiguration {
进入CacheConfigurationImportSelector类,给缓存导入配置组件
static class CacheConfigurationImportSelector implements ImportSelector {
CacheConfigurationImportSelector() {
}
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
CacheType[] types = CacheType.values();
String[] imports = new String[types.length];
for(int i = 0; i < types.length; ++i) {
imports[i] = CacheConfigurations.getConfigurationClass(types[i]);
}
return imports;
}
}
打上断点,debug
- 缓存的配置类
org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration
org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
- 哪个配置类默认生效 SimpleCacheConfiguration
application.properties中新增
debug=true
Setting——keymap——Main menu——Edit——Find
注意是在default中
设置完即可在控制台中ctrl+F查找
进入此类
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnMissingBean({CacheManager.class})
@Conditional({CacheCondition.class})
class SimpleCacheConfiguration {
SimpleCacheConfiguration() {
}
@Bean
ConcurrentMapCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers cacheManagerCustomizers) {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
List<String> cacheNames = cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames);
}
return (ConcurrentMapCacheManager)cacheManagerCustomizers.customize(cacheManager);
}
}
- 发现它给容器中注册了一个CacheManager:ConcurrentMapCacheManager
- 进入ConcurrentMapCacheManager
public class ConcurrentMapCacheManager implements CacheManager, BeanClassLoaderAware {
- 进入CacheManager
public interface CacheManager {
@Nullable
Cache getCache(String var1);
Collection<String> getCacheNames();
}
- 进入ConcurrentMapCacheManager,打个断点
进入createConcurrentMapCache方法
protected Cache createConcurrentMapCache(String name) {
SerializationDelegate actualSerialization = this.isStoreByValue() ? this.serialization : null;
return new ConcurrentMapCache(name, new ConcurrentHashMap(256), this.isAllowNullValues(), actualSerialization);
}
- 可知可以获取和创建ConcurrentMapCache类型的缓存组件;它的作用:将数据保存在ConcurrentMap中
- 进入ConcurrentMapCache,打个断点
private final ConcurrentMap<Object, Object> store;
- 给service中打上断点
ConcurrentMapCache中
ConcurrentMapCacheManager
将断点打到方法内
刷新页面
发现在还未进入service缓存方法之前先调用getCache,得到
,即
缓存名
放行.进入到
,点进generateKey
继续点进
private SingletonSupplier<KeyGenerator> keyGenerator = SingletonSupplier.of(SimpleKeyGenerator::new);
生成策略:
如果没有参数:key=new SimpleKey();
如果有一个参数:key=参数的值
如果有多个参数:key=new SimpleKey(params)
public static Object generateKey(Object... params) {
if (params.length == 0) {
return SimpleKey.EMPTY;
} else {
if (params.length == 1) {
Object param = params[0];
if (param != null && !param.getClass().isArray()) {
return param;
}
}
return new SimpleKey(params);
}
}
放行
放行
刷新请求1号数据第二次的时候
直接从缓存中拿数据,不请求方法
放行
- @Cacheable 方法运行前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建
- 去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;key是按照某种策略生成的,默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key
- 没有查到缓存就调用目标方法
- 将目标方法返回的结果放到缓存中