spring cache 抽象了cache,具体的实现可以随意组合。由于ConcurrentMapCache没有失效时间,虽然他是JVM最近的缓存,但用不好会是jvm很耗内存。所以退而求其次使用了caffeine(咖啡因缓存)这样可以实现进程缓存(有牛人可以解释下,我不是很明白什么是进程内缓存)。线面是spring整合caffeine缓存实现一二级缓存。
-
自定义缓存实现
public class MapCaffeCache implements Cache {
// private ConcurrentMapCache mapCache = new ConcurrentMapCache("mapCache");
private com.github.benmanes.caffeine.cache.@NonNull Cache<Object, Object> mapCache = Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.SECONDS).expireAfterAccess(5, TimeUnit.SECONDS).maximumSize(5).build();
private com.github.benmanes.caffeine.cache.@NonNull Cache<Object, Object> caffeCache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES).expireAfterAccess(1, TimeUnit.MINUTES).maximumSize(100).build();
private String name = "userCache";
@Override
public String getName() {
return this.name;
}
@Override
public Object getNativeCache() {
return this;
}
@Override
public ValueWrapper get(Object key) {
@Nullable
Object ob = mapCache.getIfPresent(key);
// 如果一级缓存有数据 直接返回 不触发二级缓存
if (ob != null) {
System.out.println(String.format("Cache L1 (CaffeineCache) :: %s = %s", key, ob));
SimpleValueWrapper valueWrapper = new SimpleValueWrapper(ob);
return valueWrapper;
}
Object obj = caffeCache.getIfPresent(key);
if (obj != null) {
SimpleValueWrapper valueWrapper2 = new SimpleValueWrapper(obj);
System.out.println(String.format("Cache L2 (CaffeineCache) :: %s = %s", key, obj));
// 如果二级缓存有数据 则更新到一级缓存
mapCache.put(key, obj);
return valueWrapper2;
}
return null;
}
@Override
public <T> T get(Object key, Class<T> type) {
return (T) get(key).get();
}
@Override
public <T> T get(Object key, Callable<T> valueLoader) {
return (T) get(key).get();
}
@Override
public void put(Object key, Object value) {
mapCache.put(key, value);
caffeCache.put(key, value);
}
@Override
public void evict(Object key) {
mapCache.asMap().remove(key);
caffeCache.asMap().remove(key);
}
@Override
public void clear() {
mapCache.asMap().clear();
caffeCache.asMap().clear();
}
}
-
spring配置文件配置
<cache:annotation-driven
cache-manager="cacheManager" proxy-target-class="true" />
<bean id="cacheManager"
class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<ref bean="mapCaffeCache" />
</set>
</property>
</bean>
<bean id="mapCaffeCache" class="com.app.utils.MapCaffeCache"></bean>
-
service 使用
// condition表达式为true缓存 表达式不可以和null运算、 unless返回true不缓存 unless表达式可以和null运算
// (key 也可以表示为:key = "p0" 0表示第index参数做为key)
@Cacheable(cacheManager = "cacheManager", key = "#i", value = "userCache", condition = "#i>7", unless = "#i>8")
public String getList(int i) {
return "list server method :: "
+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
@Cacheable(cacheManager = "cacheManager", key = "#i", value = "userCache")
public String getUsers(int i) {
return "list server method :: "
+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
@CachePut(cacheManager = "cacheManager", cacheNames = { "userCache" }, key = "#id")
public String userUpdate(int id) {
return "userUpdate server method :: "
+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}