博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于注解的spring缓存,轻松无侵入解决cache问题
阅读量:6263 次
发布时间:2019-06-22

本文共 3350 字,大约阅读时间需要 11 分钟。

hot3.png

之前怎么加缓存

为了加快数据获取速度,减少数据库的I/O压力,往往在业务接口中加入缓存。相信大多数人都是按照下面的方法中操作缓存:

public User getUserById(long id) {        //缓存中获取数据        if (Cache.contain(CacheKey.get(id))) {            return Cache.get(id);        }        //数据库获取数据        User user = userDao.getById();        Cache.put(CacheKey.get(id),user);        return user;    }

缓存的读取和保存已经侵入到业务代码中,后期很难维护。那么,是否有一种优雅的方法,无侵入地解决缓存问题呢?

spring提供了spring cache模块,利用注解式AOP的方式提供缓存支持。

实现

假设需要对用户业务接口的查询功能加入缓存,在更新用户信息和删除用户的时候清除缓存,保证数据一致性。为了演示,定义了用户业务类UserService。

public interface UserService {    User getById(long id);    void deleteById(long id);    void update(User user);}

###(1)业务添加缓存

配置cache的规则,例如key,cache的名字,什么情况下保存或者删除缓存。这些规则都支持SpEL表达式,关于SpEL表达式请自行了解。先看一下为了满足需求,对业务的缓存配置如下:

@Service@CacheConfig(cacheNames = {"userCache"})public class UserServiceImpl implements UserService {    @Cacheable(key = "'user:'+#id", unless = "#result == null")    @Override    public User getById(long id) {        System.out.println("getById():" + id);        return new User(id, "hugo");    }    @CacheEvict(key = "'user:'+#id")    @Override    public void deleteById(long id) {        System.out.println("deleteById():" + id);        throw new RuntimeException("deleteById()方法发生了异常");    }    @CacheEvict(key = "'user:'+#user.id")    @Override    public void update(User user) {        System.out.println("update():" + user.toString());    }}

上面使用名为userCache的缓存实例,为了演示,三个业务方法的缓存key都是以"user:id"的方式定义,这里使用SpEL表达式,spring会在运行时获取id值填入到表达式中。SpEL支持如下上下文数据: 输入图片说明

** cache注解详细解释 **

  • @Cacheable 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

    输入图片说明

  • @CachePut 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用 输入图片说明

  • @CacheEvict 主要针对方法配置,能够根据一定的条件对缓存进行清空 输入图片说明

(2)spring配置缓存

前面已经在业务方法中应用了缓存,那么接下来将在spring中定义该缓存实例。由于现在在项目中主要应用ehcache和redis作为缓存实现方案,所以下面分别对ehcache和redis两种方案的缓存进行配置。

** ehcache **

清单:applicationContext-cache-ehcache.xml

清单:ehcache.xml

** redis **

这里需要注意的是,key和value的生成方式。key 的生成器使用org.springframework.data.redis.serializer.StringRedisSerializer,该生成器获取到的key可以在任意redis客户端中通用;value使用GenericJackson2JsonRedisSerializer生成,因为jackson反序列化时需要指明类的类型,所以GenericJackson2JsonRedisSerializer将会在序列化的时候保存class类型到redis中。

另外,RedisCacheManager默认情况下是不支持单独对某个key(方法级别)设置过期时间的,这个需要进行扩展。配置文件中的expires属性的意思是对某个缓存实例设置过期时间。

清单:applicationContext-cache-redis.xml

userCache

运行测试结果如下,在redis中存储了key为userCache:user:100的缓存数据,缓存的有效期是3600秒。 输入图片说明

参考资料

转载于:https://my.oschina.net/thinwonton/blog/918163

你可能感兴趣的文章
python类库32[多进程之Pool+Logging]
查看>>
现有portal项目(商业的和开源的)解决方案及优缺点
查看>>
集群(cluster)原理(转)
查看>>
Qt简介以及如何配置Qt使用VS2010进行开发
查看>>
html、html服务器控件和web服务器控件的区别
查看>>
8天玩转并行开发——第四天 同步机制(上)
查看>>
map 取最大value
查看>>
WCF中的异步实现
查看>>
Thrift之代码生成器Compiler原理及源码详细解析2
查看>>
java垃圾回收
查看>>
案例分析:基于消息的分布式架构
查看>>
简单两步走 中兴V880获取权限方法
查看>>
外部 BLOB 存储体系结构
查看>>
导入文本文件时如何指定字段类型.sql
查看>>
C# 对象二进制序列化
查看>>
收藏的几个好的网站
查看>>
linux中shell变量$#,$@,$*,$?,$0,$1,$2的含义解释
查看>>
前端精选文摘:那些年我们一起清除过的浮动
查看>>
实现一种快速查找Richedit中可见区域内OLE对象的方法
查看>>
Java虚拟机工作原理详解 ( 二 )
查看>>