核心:使用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

springboot缓存之缓存工作原理_数据

springboot缓存之缓存工作原理_数据_02

  • 缓存的配置类

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

springboot缓存之缓存工作原理_缓存_03

springboot缓存之缓存工作原理_spring_04

注意是在default中

springboot缓存之缓存工作原理_数据_05

设置完即可在控制台中ctrl+F查找

springboot缓存之缓存工作原理_数据_06

进入此类

@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,打个断点

springboot缓存之缓存工作原理_缓存_07

进入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,打个断点

springboot缓存之缓存工作原理_spring_08


private final ConcurrentMap<Object, Object> store;


  • 给service中打上断点

springboot缓存之缓存工作原理_缓存_09

ConcurrentMapCache中

springboot缓存之缓存工作原理_spring_10

springboot缓存之缓存工作原理_缓存_11

ConcurrentMapCacheManager

springboot缓存之缓存工作原理_数据_12

将断点打到方法内

刷新页面

springboot缓存之缓存工作原理_spring_13

发现在还未进入service缓存方法之前先调用getCache,得到

springboot缓存之缓存工作原理_数据_14

,即

springboot缓存之缓存工作原理_缓存_15

缓存名

springboot缓存之缓存工作原理_spring_16

springboot缓存之缓存工作原理_spring_17

放行.进入到

springboot缓存之缓存工作原理_数据_18

springboot缓存之缓存工作原理_spring_19

,点进generateKey

springboot缓存之缓存工作原理_缓存_20

继续点进

springboot缓存之缓存工作原理_spring_21


private SingletonSupplier<KeyGenerator> keyGenerator = SingletonSupplier.of(SimpleKeyGenerator::new);


springboot缓存之缓存工作原理_spring_22

生成策略:

如果没有参数: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);
}
}

放行

springboot缓存之缓存工作原理_数据_23

放行

springboot缓存之缓存工作原理_spring_24

刷新请求1号数据第二次的时候

直接从缓存中拿数据,不请求方法

springboot缓存之缓存工作原理_缓存_25

放行

springboot缓存之缓存工作原理_spring_26

  1. @Cacheable  方法运行前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建
  2. 去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;key是按照某种策略生成的,默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key
  3. 没有查到缓存就调用目标方法
  4. 将目标方法返回的结果放到缓存中