SpringBoot缓存配置原理

1、自动配置类;CacheAutoConfiguration

自动配置类是springboot的组件加载机制中的常见类,CacheAutoConfiguration类中关键定义了导入缓存相关的配置组件

@Import({
CacheAutoConfiguration.CacheConfigurationImportSelector.class, CacheAutoConfiguration.CacheManagerEntityManagerFactoryDependsOnPostProcessor.class})

CacheConfigurationImportSelector是CacheAutoConfiguration的内部类:

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;
        }
    }

它为我们导入了相关的缓存配置类如下:

   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.GuavaCacheConfiguration
   org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默认】
   org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration

2.xxxCacheConfiguration

因为容器中加载了如上的11中cache配置类,那么如何选择匹配的配置类呢?我们不妨看看其中一个配置类SimpleCacheConfiguration:

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnMissingBean({CacheManager.class})
@Conditional({CacheCondition.class})
class SimpleCacheConfiguration {
    SimpleCacheConfiguration() {
    }

debug会发现,容器会根据配置类中的@Conditional注解进行筛选判断,最终匹配到对应的"xxxCacheConfiguration",以SimpleCacheConfiguration为例,它会在容器中注册一个ConcurrentMapCacheManager(缓存管理器),代码如下:

  	@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);
    }

3.ConcurrentMapCacheManager 缓存管理器

这个类实现了CacheManager接口,可以获取和创建ConcurrentMapCache类型的缓存组件;

public class ConcurrentMapCacheManager implements CacheManager, BeanClassLoaderAware {
    private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap(16);

	@Nullable
    public Cache getCache(String name) {                                     //根据用户定义的缓存name获取对应的缓存
        Cache cache = (Cache)this.cacheMap.get(name);
        if (cache == null && this.dynamic) {
            ConcurrentMap var3 = this.cacheMap;
            synchronized(this.cacheMap) {
                cache = (Cache)this.cacheMap.get(name);
                if (cache == null) {
                    cache = this.createConcurrentMapCache(name);        //找不到cache时则创建一个
                    this.cacheMap.put(name, cache);
                }
            }
        }

        return cache;
    }
    
	protected Cache createConcurrentMapCache(String name) {                  //创建cache存放数据,返回的实际上是个ConcurrentMapCache
        SerializationDelegate actualSerialization = this.isStoreByValue() ? this.serialization : null;
        return new ConcurrentMapCache(name, new ConcurrentHashMap(256), this.isAllowNullValues(), actualSerialization);
    }
	
 }

    

所以ConcurrentMapCache的作用就是将数据保存在ConcurrentMap中;

public class ConcurrentMapCache extends AbstractValueAdaptingCache {
	private final ConcurrentMap<Object, Object> store;
	@Nullable
    protected Object lookup(Object key) {
        return this.store.get(key);
    }

	 public void put(Object key, @Nullable Object value) {
        this.store.put(key, this.toStoreValue(value));
    }
}

它还提供了查找的相关功能如上的put()方法,是数据缓存数据获取和存放的核心。如此一来,就可将数据进行缓存。

4. 运行流程:

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

public class SimpleKeyGenerator implements KeyGenerator {
    public SimpleKeyGenerator() {
    }

    public Object generate(Object target, Method method, Object... params) {
        return generateKey(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);
        }
    }
}

SimpleKeyGenerator生成key的默认策略;
如果没有参数;key=new SimpleKey();
如果有一个参数:key=参数的值
如果有多个参数:key=new SimpleKey(params);
3、没有查到缓存就调用目标方法;
4、将目标方法返回的结果,放进缓存中

@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,
如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据;

核心:
1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件
2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值