Spring添加对缓存的支持

时间:2023-01-18 15:41:41

缓存可以可以存储经常使用到的信息,如果这些信息保存在数据库中,经常对数据库的读取会严重影响应用的性能,所以将这些信息保存在缓存中,取出来就可以立即使用。

1、启用spring对缓存的支持

Spring对缓存的支持有两种方式:

1)注解驱动缓存

2)XML申明的缓存

使用Spring最通用的方法就是在方法上添加@Cacheable和@CacheEvict注解。本人更喜欢使用XML与注解混合使用的方式开发。

2、使用XML文件配置缓存

<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd"
>


<!-- 启用缓存注解开关 -->
<cache:annotation-driven cache-manager="cacheManager"/>
<!-- 启用注解 -->
<context:component-scan base-package="com.zjp" />
<context:annotation-config/>

<bean id="ehcache" 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="ehcache"/>
</bean>

</beans>

在spring配置文件中声明了使用ehcache缓存管理器以及对应的ehcache.xml文件定义的缓存。
对应的ehcache.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">


<!-- 磁盘缓存位置 -->
<diskStore path="java.io.tmpdir/ehcache"/>

<!-- 默认缓存 -->
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxEntriesLocalDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">

<persistence strategy="localTempSwap"/>
</defaultCache>

<cache name="userCache"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="3"
timeToLiveSeconds="3"
maxEntriesLocalDisk="10000000"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU"/>

<cache name="users"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="3"
timeToLiveSeconds="3"
maxEntriesLocalDisk="10000000"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU"/>

</ehcache>

其中定义了两个缓存,分别为userCache和users。

3、为对应的方法添加注解支持缓存

为对应的方法添加上注解就可以实现对缓存的控制,常用的注解如下:

注解 作用
@Cacheable 添加缓存之前检查缓存中是否存在,存在就不调用,否则调用
@CachePut 不管缓存是否存在都调用方法
@CacheEvict 删除一条或者多条缓存
@Caching 分组的注解,可以同时应用多个缓存注解

1)添加缓存

@Cacheable和@CachePut注解都可以填充缓存,但是它们的工作方差异。
@Cacheable首先在缓存中查找条目,如果找到了匹配的条目,那么就不会对方法进行
了。如果没有找到匹配的条目,方法会被调用并且返回值要放到缓存之中。而@Cache
不会在缓存中检查匹配的值,目标方法总是会被调用,并将返回值添加到缓存之中。
a、自定义缓存key
@Cacheable和@CachePut都有一个名为key属性,这个属性能够替换默认的key,它是通过
一个SpEL表达式计算得到的。任意的SpEL表达式都是可行的,但是更常见的场景是所定义的
表达式与存储在缓存中的值有关,据此计算得到key。

 @CachePut(value = "users", key = "#user.getId()")
public void updateUser(User user) {
userDao.updateUser(user);
}

b、条件化缓存
@Cacheable和@CachePut提供了两个属性用以实现条件化缓存:unless和condition,
这两个属性都接受一个SpEL表达式。如果unless属性的SpEL表达式计算结果为true,那么
缓存方法返回的数据就不会放到缓存中。与之类似,如果condition属性的SpEL表达式计算
结果为false,那么对于这个方法缓存就会被禁用掉。

 @Cacheable(value = "users", condition = "#user.getId() <= 2")// 当id>2的时候禁用缓存
public User findUserInLimit(User user) {
return userDao.findUserById(user.getId());
}

2)缓存的移除

使用@CacheEvict 就可以移除缓存中对应的数据。
对于缓存操作的UserService如下:

@Service
public class UserService {

@Autowired
private UserDao userDao;

@Cacheable({"users"})
public User findUser(User user) {
System.out.println("userDao--"+userDao);
User findUserById = userDao.findUserById(user.getId());//数据库
System.out.println("user---"+findUserById);
return userDao.findUserById(user.getId());//数据库
}

@Cacheable(value = "users", condition = "#user.getId() <= 2")// 当id>2的时候禁用缓存
public User findUserInLimit(User user) {
return userDao.findUserById(user.getId());
}

@CachePut(value = "users", key = "#user.getId()")
public void updateUser(User user) {
userDao.updateUser(user);
}

@CacheEvict(value = "users")
public void removeUser(User user) {
userDao.removeUserById(user.getId());
}

@CacheEvict(value = "users", allEntries = true)
public void clear() {
userDao.removeAllUser();
}
}

同时添加上其他的


public interface UserDao {

/**
* 删除所有用户
*/

public void removeAllUser();
/**
* 根据Id查询用户
* @param id
* @return
*/

public User findUserById(long id);
/**
* 更新用户
* @param user
*/

public void updateUser(User user);
/**
* 根据Id删除用户
* @param id
*/

public void removeUserById(long id);

}
package com.zjp.service.impl;

import org.springframework.stereotype.Service;

import com.zjp.domain.User;
import com.zjp.service.UserDao;

@Service
public class UserDaoImpl implements UserDao{

public void removeAllUser() {
// TODO Auto-generated method stub

}

public User findUserById(long id) {
User user = new User();
user.setId(123424);
user.setPassword("ahfakjbnfjk");
user.setUsername("lisi");
return user;
}

public void updateUser(User user) {
// TODO Auto-generated method stub

}

public void removeUserById(long id) {
// TODO Auto-generated method stub

}

}