1. 不使用框架的缓存方案
第三方的缓存实现已经有很多,有 guava cache、redis、tair等,它们解决的是缓存的底层问题。
在不使用框架的情况下,参考之前的wikiGuava cache,在项目直接使用内存缓存。
在业务逻辑比较简单时,使用这种方式简答可靠,实现成本较低。不过在业务场景比较复杂的场景下,这种使用方式的缺点有
- 缓存逻辑与业务逻辑紧耦合
- 替换第三方缓存解决方案比较困难
2. spring的缓存解决方案
spring的缓存技术是一种对具体缓存技术使用的抽象,它是一层wrapper,提供出统一的API接口。再结合spring的AOP特性,可以在代码中使用注解来使用缓存。
所以spring的缓存解决方案天生具备以下特点
- 缓存与业务隔离,支持多种第三方缓存技术
- 使用方便,在代码中需要使用缓存的方法上添加注解即可
- 支持自定义的缓存方案
2.1. 添加xml配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd">
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true" />
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean
class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
p:name="default" />
</set>
</property>
</bean>
</beans>
<cache:annotation-driven />,spring支持缓存的配置项,它缺省使用名叫
cacheManager 的缓存管理器,不过也可以指定cache-manage属性。
cache-manage这个bean使用了 org.springframework.cache.support.SimpleCacheManager,spring的缓存管理的缺省实现,有个名字为default的集合,它是基于 java.util.concurrent.ConcurrentHashMap 的一个缓存存储集合。
这些配置指明了缓存管理的bean,它利用java.util.concurrent.ConcurrentHashMap来缓存数据,实现了读写缓存等操作。
2.2. 使用cache
spring缓存方案的注解主要有
-
@Cacheable 注解,对方法配置,它的含义是将指定的key/value存储到指定的缓存中如default,value就是该方法的返回。当调用方法时,现在缓存寻找key是否存在,如果存在则返回缓存中的结果,并不执行真正的方法。
@Cacheable(value = "default", key = "'operationLog:'+#id")
public OperationLog getById(Long id) {
return operationLogDAO.getById(id);
}
- @CachePut 注解,对方法配置,既可以保证将key/value写到缓存中,又能保证方法被执行,使用场景是更新缓存的值(update操作)或者保证方法必须被执行(比如记录日志、发送信息等)。
@CachePut(value = "default", key = "'operationLog:'+#id")
public OperationLog update(Long id) {
return operationLogDAO.updateById(id);
}
- @CachEvict注解,对方法配置,对缓存的key/value进行清空,即对应删除操作。
@CachePut(value = "default", key = "'operationLog:'+#id")
public int delete(Long id) {
return operationLogDAO.deleteById(id);
}
3. spring缓存方案扩展
3.1. 实现cache
实现一个接口类Cache,主要的几个方法有get、put、evict。
public interface Cache {
String getName();
Object getNativeCache();
Cache.ValueWrapper get(Object var1);
<T> T get(Object var1, Class<T> var2);
void put(Object var1, Object var2);
void evict(Object var1);
void clear();
public interface ValueWrapper {
Object get();
}
}
public class MyCache implements Cache {
//...
}
具体的缓存实现spring不关心,你可以利用medis、tair、guava cache的API来填充这些方法即可。
3.2. 实现cacheManage
实现接口类AbstractCacheManager
public class MyCacheManager extends AbstractCacheManager {
private Collection<? extends MyCache> caches;
public void setCaches(Collection<? extends MyCache> caches) {
this.caches = caches;
}
@Override
protected Collection<? extends MyCache> loadCaches() {
return this.caches;
}
}
3.3. 配置xml
告诉spring我们要使用自定义的缓存实现。
<bean id="myCache" class="MyCache" />
<bean id="cacheManager" class="MyCacheManager">
<property name="caches" ref="myCache">
</property>
</bean>