只要添加如下依赖,即可使用缓存功能。
org.springframework.boot
spring-boot-starter-cache
:在主入口类上添加该注解,用于开启缓存;
@CacheConfig:标注在类上,表示当前类使用的缓存组件中的key为该注解指定的cacheNames/value,当该注解指定了cacheNames/value之后,@Cacheable上就无需再使用cacheNames/value了;
@Cacheable:将方法的结果进行缓存;
cacheNames/value:缓存组件的名字;
key:缓存数据使用的key,默认是使用方法参数的值,可以使用SpEL表达式,比如#id == #a0 == #p0 == #root.args[0]都表示使用第一个参数的值作为缓存的key;
keyGenerator:key的生成器,可以自己指定key的生成器的组件id;
cacheManager:指定缓存管理器;
cacheResolver:指定获取解析器;
condition:指定符合条件的情况下才缓存,支持SpEL表达式;
condition=“#id>1”:表示id的值大于1时才缓存。
unless:否定缓存,当unless指定的条件为true,方法的返回值就不会被缓存,该属性可以获取到结果进行判断,unless与condition刚好相反;
unless=“#a0==2”:表示第一个参数的值为2时,查询结果不缓存。
sync:是否使用异步模式,使用sync后unless就不支持了;
其中keyGenerator与key二者只能选一,cacheResolver与cacheManager也二者选一。
@CachePut:用于更新缓存,它先调用方法,然后将目标方法的结果进行缓存。
能够更新缓存的前提是,@CachePut更新使用的key与@Cacheable使用的key要保持一致。
@CachePut注解属性同@Cacheable的属性类似,少了sync属性。
@CacheEvict:缓存清除
同样如果要清除缓存,则使用的key值要与@Cacheable使用的key一致,否则达不到清除缓存的功能。
@CacheEvict注解属性比@Cacheable注解少了sync和unless,但是多了两个属性:allEntries和beforeInvocation。
allEntries:表示是否删除所有缓存。
beforeInvocation:表示删除缓存的操作是否在目标方法执行之前。
@Configuration
@ConditionalOnClass(CacheManager.class)
@ConditionalOnBean(CacheAspectSupport.class)
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureBefore(HibernateJpaAutoConfiguration.class)
@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class,
RedisAutoConfiguration.class })
@Import(CacheConfigurationImportSelector.class)
public class CacheAutoConfiguration {
//other code...
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;
}
}
}
经过如上代码,imports保存了默认支持的缓存配置类(有顺序):
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
@Configuration
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class SimpleCacheConfiguration {
private final CacheProperties cacheProperties;
private final CacheManagerCustomizers customizerInvoker;
SimpleCacheConfiguration(CacheProperties cacheProperties,
CacheManagerCustomizers customizerInvoker) {
this.cacheProperties = cacheProperties;
this.customizerInvoker = customizerInvoker;
}
@Bean
public ConcurrentMapCacheManager cacheManager() {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
List cacheNames = this.cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames);
}
return this.customizerInvoker.customize(cacheManager);
}
}
ConcurrentMapCacheManager类型的cacheManager组件。
public class ConcurrentMapCacheManager implements CacheManager, BeanClassLoaderAware {
private final ConcurrentMap cacheMap = new ConcurrentHashMap(16);
//other code...
//从缓存ConcurrentMap对象中获取cacheNames/value指定的Cache对象。
@Override
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;
}
protected Cache createConcurrentMapCache(String name) {
SerializationDelegate actualSerialization = (isStoreByValue() ? this.serialization : null);
return new ConcurrentMapCache(name, new ConcurrentHashMap
ConcurrentMapCache类型的缓存组件,作用是将数据保存在ConcurrentMap对象中。
public class ConcurrentMapCache extends AbstractValueAdaptingCache {
//真实用于存储缓存数据的属性
private final ConcurrentMap
1)、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字去缓存中获取(CacheManager先获取相应的缓存),第一次获取缓存,如果没有Cache组件,则会自动创建。
2)、去Cache中查找缓存的内容,使用一个key(默认是方法的参数),其中key是按照某种策略生成的,默认是使用SimpleKeyGenerator生成的。
SimpleKeyGenerator生成key的策略:
如果没有参数,key=new SimpleKey();
如果有一个参数,key=参数值
如果有多个参数,key=new SimpleKey(params);
3)、没有查到缓存,就调用目标方法;如果查到缓存,则直接返回结果,不调用目标方法。
4)、没有查到缓存后去调用目标方法,然后将目标方法返回的结果放进缓存。
自定义key:
methodName:当前被调用的方法名,例如#root.methodName
method:当前被调用的方法,例如#root.method.name
target:当前被调用的目标对象,例如#root.target
targetClass:当前被调用的目标对象类,例如#root.targetClass
args:当前被调用的方法的参数列表,例如#root.args[0]
caches:当前方法调用使用的缓存列表,
argument name:方法参数的名字,可以直接#参数名,也可以使用#a0或者#p0的形式,0表示参数索引,例如#id,#a0,#p0等。
例如:
@Cacheable(cacheNames = "emp", key = "#root.methodName+'[' + #id + ']'")
当然也可以自定义KeyGenerator:
@Bean("myKeyGenerator")
public KeyGenerator keyGenerator(){
return (target, method, params) -> method.getName() + "[" + Arrays.asList(params).toString() + "]";
}
则在@Cacheable上使用该自定义的KeyGenerator:
@Cacheable(cacheNames = "emp", keyGenerator = "myKeyGenerator")
它主要用于更新缓存,它先调用方法,然后将目标方法的结果进行缓存。但是能够更新缓存的前提是,@CachePut更新使用的key与@Cacheable使用的key要保持一致。
@Cacheable(cacheNames = "emp", key = "#a0")
public Employee getById(Integer id){}
@CachePut(cacheNames = "emp", key = "#result.id")
public Employee update(Employee employee){}
其中#result表示目标方法的返回值。因为@CachePut更新缓存比目标方法晚,所有@CachePut能获取到返回值。而@Cacheable比目标方法早,所以无法使用#result。
同样如果要清除缓存,则使用的key值要与@Cacheable使用的key一致,否则达不到清除缓存的功能。
属性allEntries,默认为false,表示不把cacheNames里所有的缓存都删除掉。当该值为true的时候,会把缓存中对应的cacheNames里的所有缓存都删除。
属性beforeInvocation,默认为false,表示删除缓存的操作在目标方法执行之后。当该值为true的时候,则删除缓存的操作在目标方法执行之前。区别:如果设为true,当目标方法执行出现异常后,对应的缓存已经被删除了。如果设为false(默认),当目标方法执行出现异常后,就不会把缓存删除掉。
====================打个广告,欢迎关注====================
QQ: |
412425870 |
微信公众号:Cay课堂 |
|
csdn博客: |
http://blog.csdn.net/caychen |
码云: |
https://gitee.com/caychen/ |
github: |
https://github.com/caychen |
点击群号或者扫描二维码即可加入QQ群: 328243383(1群) |
|
点击群号或者扫描二维码即可加入QQ群: 180479701(2群) |