缓存可以存储经常用到的数据到内存或者落地到文件中,这样在用的时候就可以快速的、不用经过计算就能拿到数据。
缓存有利也有弊,因为数据被缓存起来了,所以在时效性方面就不是很好了,所以在使用缓存的时候,应该分析一下适合的场景,并且要有一定的管理策略。
spring自身并没有实现缓存解决方案,但是它对缓存功能提供了声明式的支持,能够与多种流行的缓存实现集成。
特点:
1. 支持XML和annotation注解,使用方便。
2. 支持开箱即用 Out-Of-The-Box,不用安装其它应用服务。
3. 支持 Spring Express Language,能使用对象的任何属性或者方法来定义缓存的 key 和 condition
4. 具有相当的灵活性和扩展性。
Spring对缓存的支持有两种方式:
- 注解驱动的缓存:这种方式是当前最流行的、也是使用起来比较便捷的一种方式。
- XML配置的缓存:xml方式的配置虽然比较古老了,但是它也有自身的一些优点,比如在一些第三方jar包,我们不能在它的代码里面添加注解,就可以使用xml对相应的路径、类进行一些匹配。
缓存管理器是Spring缓存抽象的核心,它能够与多个流行的缓存实现集成。
Spring3.1内置了五个缓存管理器实现:
- SimpleCacheManager
- NoOpCacheManager
- ConcurrentMapCacheManager
- CompositeCacheManager
- EhCacheCacheManager
Spring3.2引入了另外一个缓存管理器,这个管理器可以用在基于Jcache(JSR-107)的缓存供应商之中。除了核心的spring框架,spring data又提供了两个缓存管理器:
- RedisCacheManager
- GemfireCacheManager
JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
spring3.2在线源码
可以看到,在为spring的缓存抽象选择缓存管理器时,我们有很多可选方案。具体的选择要看我们需要的应用场景,根据我们的需求选择合适的供应商,然后在使用匹配的缓存管理器。
注解 | 描述 |
---|---|
@Cacheable | 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 |
@CachePut | 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用 |
@CacheEvict | 主要针对方法配置,能够根据一定的条件对缓存进行清空 |
@Caching | 这是一个分组的注解,能够同时应用多个其他的缓存注解 |
@Cacheable(value="cache1",key=#id)
public User find(int id) {
return getUser(id);
}
@Cacheable(value="cache1",key="#id",condition="#object_type==0")
public JsonArray getCredit(int id,String object_type) {
return getUser(id);
}
//每次都会执行方法,并将结果存入指定的缓存中,当用户注册完,在另一个方法就可以直接从相应的缓存中取出用户信息而不需要再查询数据库
@CachePut(value="users",key="#user.id")
public User register(User user) {
return user;
}
@Cacheable(value="users",key="#id")
public User getUserInfo(String id) {
return find(id);
}
@CacheEvict(value="accountCache",key="#account.getName()")// 清空accountCache 中指定key值的缓存
public void updateAccount(Account account) {
updateDB(account);
}
@CacheEvict(value="accountCache",allEntries=true)// 清空accountCache 缓存
public void reload() {
reloadAll()
}
在同一个方法上可以同时使用多种注解
@Caching(evict={@CacheEvict(“a1”),@CacheEvict(“a2”,allEntries=true)})
caching注解的源码如下,可以看到我们可以同时使用(cacheable/put/evict方法)
public @interface Caching {
Cacheable[] cacheable() default {};
CachePut[] put() default {};
CacheEvict[] evict() default {};
}
属性名称 | 描述 | 示例 |
---|---|---|
methodName | 当前方法名 | root.methodName |
method | 当前被调用的对象 | root.method.name |
target | 当前被调用的对象的class | root.target |
targetClass | 当前被调用的对象的class | root.targetClass |
args | 当前方法参数组成的数组 | root.args[0] |
caches | 当前被调用的方法使用的Cache | root.caches[0].name |
当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。如:
@Cacheable(value={"users", "xxx"}, key="caches[1].name")
public User find(User user) {
returnnull;
}
EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider,也是JAVA领域应用最为广泛的缓存。
需要的依赖包
spring依赖:spring-context、spring-context-support
ehcache:ehcache
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
<bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="cacheManagerFactory"/>
bean>
<ehcache>
<diskStore path="c:/temp"/>
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"/>
<cache name="corporate"
maxElementsOnDisk="20000"
maxElementsInMemory="2000"
eternal="true"
overflowToDisk="true"
diskPersistent="true"/>
<cache name="bm"
maxElementsOnDisk="20000"
maxElementsInMemory="2000"
eternal="true"
overflowToDisk="true"
diskPersistent="true"/>
<cache name="resource_info"
maxElementsOnDisk="20000"
maxElementsInMemory="2000"
eternal="true"
overflowToDisk="true"
diskPersistent="true"
timeToLiveSeconds="1800"
/>
ehcache>
从上面的ehcache缓存配置我们知道ehcache支持将缓存落地成文件,这样启动的时候我们就可以先把落地的文件加载到内存里面。
要配置个监听器,在服务关闭的时候将缓存落地成文件
web.xml配置
<listener>
<listenerclass>
net.sf.ehcache.constructs.web.ShutdownListener
listener-class>
listener>
在系统启动时,应该添加如下属性
System.setProperty("net.sf.ehcache.enableShutdownHook", "true");
系统关闭的时候会生成一个.index后缀的文件,启动的时候会从这个文件读出数据到内存。
如果直接在IDEA工具按下关闭的按钮是没用的,可能这个按钮不是调用服务正常的关闭命令,移动到tomcat关闭的时候是可以的。