总结
- SpringCache定义了@Cacheable、@CachePut、@CacheEvict三个注解,分别对应查询、更新、删除时对缓存的处理
- 只需要在Server类添加该注解,就可以通过AOP自动代理实现缓存查询、缓存更新、缓存删除,使用形式如下,@Cacheable、@CachePut会在unless条件成立时将返回值添加进缓存,而@Cacheable在有缓存时不会执行Server类方法。@CacheEvict会直接删除缓存名为value的缓存中的键值对的键为key的键值对
@Override
@Cacheable(value = "userCache", key = "#id", unless = "#result == null")
public User getUserById(Long id) {
System.out.println("运行");
return userMapper.selectById(id);
}
@Override
@CachePut(value = "userCache", key = "#user.id", unless = "#result == null")
public User updateUser(User user) {
userMapper.updateById(user);
return userMapper.selectById(user.getId());
}
@Override
@CacheEvict(value = "userCache", key = "#id")
public void deleteUserById(Long id) {
userMapper.deleteById(id);
}
-
缓存的name为userCache,也就是下面接口方法对应的缓存名字,key就是通过name获取后,该缓存类似Map结构,可以根据key存储值和取出值,@Cacheable也是根据每次需要执行的代码key是否在缓存中存在来决定是否执行,存在则不执行 -
而SpringCache通过注解实现缓存实际上的逻辑是在CacheManager和Cache中定义的,在CacheManager使用缓存名字value,获取缓存Cache,然后缓存Cache中定义了对键值对增删查改的方法,通过这种接口抽象,可以自定义缓存,也可以整合第三方缓存,如本地缓存Caffeine和分布式缓存Redisson -
整合本地缓存Caffeine和分布式缓存Redisson,只需使用注解@EnableCaching,这是SpringCache的注解,在该注解下的类注册一个CacheManager即整合成功
@Configuration
@EnableCaching
public class CaffeineConfig {
@Bean
public Caffeine caffeineConfig() {
return
Caffeine.newBuilder()
.maximumSize(10000).
expireAfterWrite(60, TimeUnit.MINUTES);
}
@Bean
public CacheManager cacheManager(Caffeine caffeine) {
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
caffeineCacheManager.setCaffeine(caffeine);
return caffeineCacheManager;
}
}
@Configuration
@EnableCaching
public class RedissonConfig {
@Bean(destroyMethod = "shutdown")
public RedissonClient Redisson() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://127.0.0.1:6379");
return Redisson.create(config);
}
@Bean
CacheManager cacheManager(RedissonClient RedissonClient) {
Map<String, CacheConfig> config = new HashMap<String, CacheConfig>();
config.put("UserCache",
new CacheConfig(
24 * 60 * 1000,
12 * 60 * 1000));
return new RedissonSpringCacheManager(RedissonClient, config);
}
}
CacheManager接口方法
方法名 | 作用 |
---|
Cache getCache(String name) | 获取与给定名称关联的缓存 | Collection< String> getCacheNames() | 获取此管理器已知的缓存名称的集合 |
Cache接口方法
方法名 | 作用 |
---|
String getName() | 返回缓存的名称,也就是缓存关联的名称 | Object getNativeCache() | 返回基础缓存提供程序 | ValueWrapper get(Object key) | 在该缓存中查找该键key对应的值。如果缓存不包含该键的映射,则直接返回null,否则,缓存的值将在ValueWrapper中返回,ValueWrapper内只有一个get()方法用于获取值,这样设计的原因是表示存在该缓存,但其值为空 | T get(Object key, Class type) | 返回此缓存将指定键key映射到的值,并将其转换为类Class的对象 | T get(Object key, Callable valueLoader) | 返回此缓存将指定键key映射到的值,必要时从Callable类调用方法获取该值,这个必要时完全取决于自己实现,可以将在该缓存不存在时调用Callable的call方法获取一个值并返回 | void put(Object key, Object value) | 将指定的值value与此缓存中的指定键key相关联。如果缓存以前包含此键的映射,则旧值将替换为指定值 | void evict(Object key) | 如果存在此键key的映射,则从缓存中删除该键值对 | void clear() | 清空缓存中所有映射,即清空所有键值对 |
自定义SpringCache
MyCacheConfig.java 配置类
@Configuration
@EnableCaching
public class MyCacheConfig {
@Bean
CacheManager cacheManager() {
return new MyCacheManager();
}
}
MyCacheManager.java 缓存管理器类,实现CacheManager接口
public class MyCacheManager implements CacheManager {
private Map<String, Cache> map = new HashMap<>();
@Nullable
@Override
public Cache getCache(String name) {
Cache cache = map.get(name);
if (cache == null) {
cache = new MyCache(name);
map.put(name, cache);
}
return cache;
}
@Override
public Collection<String> getCacheNames() {
return map.keySet();
}
}
MyCache.java 缓存类,实现Cache接口
public class MyCache implements Cache {
private String name;
private Map<Object, ValueWrapper> map = new HashMap<>();
public MyCache(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public Object getNativeCache() {
return map;
}
@Nullable
@Override
public ValueWrapper get(Object key) {
return map.get(key);
}
@Nullable
@Override
public <T> T get(Object key, @Nullable Class<T> type) {
ValueWrapper valueWrapper = map.get(key);
if (valueWrapper != null) {
return (T) valueWrapper.get();
}
return null;
}
@Nullable
@Override
public <T> T get(Object key, Callable<T> valueLoader) {
ValueWrapper valueWrapper = map.get(key);
if (valueWrapper != null) {
return (T) valueWrapper.get();
}
T call = null;
try {
call = valueLoader.call();
} catch (Exception e) {
e.printStackTrace();
}
return call;
}
@Override
public void put(Object key, @Nullable Object value) {
map.put(key, new ValueWrapper() {
private Object v = value;
@Nullable
@Override
public Object get() {
return v;
}
});
}
@Override
public void evict(Object key) {
map.remove(key);
}
@Override
public void clear() {
map.clear();
}
}
|