缓存工作原理
自动配置类:CacheAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(CacheManager.class)
@ConditionalOnBean(CacheAspectSupport.class)
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class,
HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class })
@Import({ CacheConfigurationImportSelector.class, CacheManagerEntityManagerFactoryDependsOnPostProcessor.class })
public class CacheAutoConfiguration {
@Bean
@ConditionalOnMissingBean
//缓存管理器的自定义器
public CacheManagerCustomizers cacheManagerCustomizers(ObjectProvider<CacheManagerCustomizer<?>> customizers) {
return new CacheManagerCustomizers(customizers.orderedStream().collect(Collectors.toList()));
}
@Bean
public CacheManagerValidator cacheAutoConfigurationValidator(CacheProperties cacheProperties,
ObjectProvider<CacheManager> cacheManager) {
return new CacheManagerValidator(cacheProperties, cacheManager);
}
@ConditionalOnClass(LocalContainerEntityManagerFactoryBean.class)
@ConditionalOnBean(AbstractEntityManagerFactoryBean.class)
static class CacheManagerEntityManagerFactoryDependsOnPostProcessor
extends EntityManagerFactoryDependsOnPostProcessor {
CacheManagerEntityManagerFactoryDependsOnPostProcessor() {
super("cacheManager");
}
}
/**
* Bean used to validate that a CacheManager exists and provide a more meaningful
* exception.
*/
static class CacheManagerValidator implements InitializingBean {
private final CacheProperties cacheProperties;
private final ObjectProvider<CacheManager> cacheManager;
CacheManagerValidator(CacheProperties cacheProperties, ObjectProvider<CacheManager> cacheManager) {
this.cacheProperties = cacheProperties;
this.cacheManager = cacheManager;
}
@Override
public void afterPropertiesSet() {
Assert.notNull(this.cacheManager.getIfAvailable(),
() -> "No cache manager could be auto-configured, check your configuration (caching type is '"
+ this.cacheProperties.getType() + "')");
}
}
/**
* {@link ImportSelector} to add {@link CacheType} configuration classes.
*/
static class CacheConfigurationImportSelector implements ImportSelector {
@Override
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;
}
}
}
哪个配置类能生效:SimpleCacheConfiguration
@Configuration(proxyBeanMethods = false)
//如果容器中有cache组件
@ConditionalOnBean(Cache.class)
//如果容器中没有CacheManager组件
@ConditionalOnMissingBean(CacheManager.class)
//满足这个条件
@Conditional(CacheCondition.class)
class GenericCacheConfiguration {
@Bean
SimpleCacheManager cacheManager(CacheManagerCustomizers customizers, Collection<Cache> caches) {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(caches);
return customizers.customize(cacheManager);
}
}
SimpleCacheConfiguration
源码:
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class SimpleCacheConfiguration {
@Bean
//给容器中注册了一个缓存管理器CacheManager:ConcurrentMapCacheManager
//可以获取和创建ConcurrentMapCache类型的缓存组件,作用:将数据保存在ConcurrentMap中
ConcurrentMapCacheManager cacheManager(CacheProperties cacheProperties,
CacheManagerCustomizers cacheManagerCustomizers) {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
List<String> cacheNames = cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames);
}
return cacheManagerCustomizers.customize(cacheManager);
}
}
ConcurrentMapCacheManager
源码:
public class ConcurrentMapCacheManager implements CacheManager, BeanClassLoaderAware {
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);
@Override
@Nullable
public Cache getCache(String name) {
//根据名字获取组件
Cache cache = this.cacheMap.get(name);
if (cache == null && this.dynamic) {
synchronized (this.cacheMap) {
cache = this.cacheMap.get(name);
if (cache == null) {
//创建缓存对象
cache = createConcurrentMapCache(name);
this.cacheMap.put(name, cache);
}
}
}
return cache;
}
createConcurrentMapCache()//创建缓存对象
源码:
protected Cache createConcurrentMapCache(String name) {
SerializationDelegate actualSerialization = (isStoreByValue() ? this.serialization : null);
return new ConcurrentMapCache(name, new ConcurrentHashMap<>(256),
isAllowNullValues(), actualSerialization);
}
}
CacheManager
源码:
public interface CacheManager {
//根据名字得到缓存组件
@Nullable
Cache getCache(String name);
}
ConcurrentMapCache
源码:
public class ConcurrentMapCache extends AbstractValueAdaptingCache {
protected ConcurrentMapCache(String name, ConcurrentMap<Object, Object> store,
boolean allowNullValues, @Nullable SerializationDelegate serialization) {
super(allowNullValues);
Assert.notNull(name, "Name must not be null");
Assert.notNull(store, "Store must not be null");
this.name = name;
this.store = store;
this.serialization = serialization;
}
//查询缓存的数据lookup
@Override
@Nullable
protected Object lookup(Object key) {
return this.store.get(key);
}
//保存数据
@Override
public void put(Object key, @Nullable Object value) {
this.store.put(key, toStoreValue(value));
}
store
源码:
private final ConcurrentMap<Object, Object> store;
}
运行流程
核心:
1.使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件
2.key使用keyGenerayor生成的,默认是SimpleKeyGenerator
@Cacheable
1.方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取
(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建,放到cacheMap里
2.去Cache中查找缓存的内容,使用一个key,默认就是方法的参数
key是按照某种策略生成,默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator 生成key
public abstract class CacheAspectSupport extends AbstractCacheInvoker implements BeanFactoryAware, InitializingBean, SmartInitializingSingleton {
@Nullable
private Cache.ValueWrapper findCachedItem(Collection<CacheOperationContext> contexts) {
Object result = CacheOperationExpressionEvaluator.NO_RESULT;
for (CacheOperationContext context : contexts) {
if (isConditionPassing(context, result)) {
//生成key
Object key = generateKey(context, result);
Cache.ValueWrapper cached = findInCaches(context, key);
if (cached != null) {
return cached;
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No cache entry for key '" + key + "' in cache(s) " + context.getCacheNames());
}
}
}
}
return null;
}
//生成key
private Object generateKey(CacheOperationContext context, @Nullable Object result) {
//调用上下文,生成key
Object key = context.generateKey(result);
if (key == null) {
throw new IllegalArgumentException("Null key returned for cache operation (maybe you are " +
"using named params on classes without debug info?) " + context.metadata.operation);
}
if (logger.isTraceEnabled()) {
logger.trace("Computed cache key '" + key + "' for operation " + context.metadata.operation);
}
return key;
}
//调用上下文,生成key
@Nullable
protected Object generateKey(@Nullable Object result) {
if (StringUtils.hasText(this.metadata.operation.getKey())) {
EvaluationContext evaluationContext = createEvaluationContext(result);
return evaluator.key(this.metadata.operation.getKey(), this.metadata.methodKey, evaluationContext);
}
//
return this.metadata.keyGenerator.generate(this.target, this.metadata.method, this.args);
}
keyGenerator
源码:
private final KeyGenerator keyGenerator;
}
KeyGenerator
源码:
@FunctionalInterface
public interface KeyGenerator {
Object generate(Object target, Method method, Object... params);
}
SimpleKeyGenerator
实现:KeyGenerator
public class SimpleKeyGenerator implements KeyGenerator {
}
3.没有查到缓存就调用目标方法
4.将目标方法返回的结果,放进缓存中
@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存
如果没有就运行方法并将结果放入缓存,以后在来调用就可以直接使用缓存中的数据
SimpleKeyGenerator 生成key的默认策略
如果没有参数,key=new SimpleKey();
如果有一个参数,key=参数的值
如果有多个参数,key=new SimpleKey(params);
generateKey
源码:
public class SimpleKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
return generateKey(params);
}
/**
* Generate a key based on the specified parameters.
*/
public static Object generateKey(Object... params) {
//如果没有参数
if (params.length == 0) {
return SimpleKey.EMPTY;
}
//如果有一个参数就把这个参数返回
if (params.length == 1) {
Object param = params[0];
if (param != null && !param.getClass().isArray()) {
return param;
}
}
return new SimpleKey(params);
}
}
EMPTY
源码:
@SuppressWarnings("serial")
public class SimpleKey implements Serializable {
public static final SimpleKey EMPTY = new SimpleKey();
}
之前已经运行过一次,这里有数据,直接从缓存拿数据
数据不为空