侧边栏壁纸
  • 累计撰写 47 篇文章
  • 累计创建 22 个标签
  • 累计收到 27 条评论

目 录CONTENT

文章目录

Spring Cache 常用注解

vchopin
2022-06-08 / 1 评论 / 0 点赞 / 231 阅读 / 3,553 字

1. Spring Cache

Spring Cache 是Spring 提供的一整套的缓存解决方案,它不是具体的缓存实现,它只提供一整套的接口和代码规范、配置、注解等,用于整合各种缓存方案,比如Redis、Memcached、Guava、Caffeine,其中Redis和Memcached使用的较多,各自也有不同的优缺点。

2. @CacheConfig

在同个service类下,我们对不同方法添加的注解都要指定同一个缓存组件我们可以在类头上统一抽取缓存组件。

例如:

@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "job")
public class JobServiceImpl implements JobService {
	...
}

在CacheConfig中指定了cacheNames的话,则相当于为后续所有方法都加了cacherName或者value指定的组件并且这个组件来自@CacheConfig

2. @Cacheable

这个注解主要用来配置方法,能够根据方法的请求参数对其结果进行缓存。即当重复使用相同参数调用方法的时候,方法本身不会被调用执行,即方法本身被略过了,取而代之的是方法的结果直接从缓存中找到并返回了。

简单来说,这个方法就是开启缓存,一般用在find方法上。

参数:

  • value:缓存的名字,如果在之前的类上指定了@CacheConfig,则不必指定。

  • key:缓存的key,可以为空,如果指定要按照SpEL表达式编写;如果不指定,则缺省按照方法的所有参数进行组合。

  • condition:缓存的条件,可以为空,使用SpEL编写,返回true或者false,只有为true才能缓存。

例子:

    @Override
    @Cacheable(key = "'id:' + #p0")
    public JobDto findById(Long id) {
        Job job = jobRepository.findById(id).orElseGet(Job::new);
        ValidationUtil.isNull(job.getId(),"Job","id",id);
        return jobMapper.toDto(job);
    }

上述代码的意思是指,缓存的名字为Service上指定的名字,此时缓存的key值为id:id的值。其中#p0的意思是指加有@Cacheable注解的方法中的第一个参数,此处是指参数Long id

3. @CacheEvict

主要对方法配置,用来标记要清空缓存的方法,当这个方法被调用并满足一定条件后,即会清空缓存。常用在delete方法

参数:

  • value:缓存的位置,不能为空(CacheConfig除外)。
  • key:缓存的key,默认为空。
  • condition:触发的条件,只有满足条件的情况才会清除缓存,默认为空,支持SpEL。
  • allEntries:true表示清除value中的全部缓存,默认为false。

例子:

    @Override
    @CacheEvict(key = "'id:' + #p0.id",condition="#p0['id']>0")
    @Transactional(rollbackFor = Exception.class)
    public void update(Job resources) {
        Job job = jobRepository.findById(resources.getId()).orElseGet(Job::new);
        Job old = jobRepository.findByName(resources.getName());
        if(old != null && !old.getId().equals(resources.getId())){
            throw new EntityExistException(Job.class,"name",resources.getName());
        }
        ValidationUtil.isNull( job.getId(),"Job","id",resources.getId());
        resources.setId(job.getId());
        jobRepository.save(resources);
    }

上面两行代码表示,只要resources中key为id的值大于0,将清除缓存,否则直接调用update方法。

上述代码中,如果设置了allEntries=True表示,只要执行了update方法,就刷新缓存名为CacheConfig中指定的所有缓存。

4.@CachePut

该注解主要针对方法的配置,能够根据方法的请求参数对其结果进行缓存,和@Cacheable不同的是,它每次都会触发真实方法的调用。

    @Override
    @CachePut(key = "'config'")
    @Transactional(rollbackFor = Exception.class)
    public QiniuConfig config(QiniuConfig qiniuConfig) {
        qiniuConfig.setId(1L);
        String http = "http://", https = "https://";
        if (!(qiniuConfig.getHost().toLowerCase().startsWith(http)||qiniuConfig.getHost().toLowerCase().startsWith(https))) {
            throw new BadRequestException("外链域名必须以http://或者https://开头");
        }
        return qiNiuConfigRepository.save(qiniuConfig);
    }

上面代码表示,当调用config方法时,该方法体会被执行,并且执行的结果会返回写入到缓存中。常用在create方法上。

5. 为什么缓存用redis而不用mongo

之前有个项目没用redis做缓存,也没用sql数据库,而是直接用mongo做存储。现在刚好用到redis,正好思考一下这两者的区别。

从内存管理方式来说:
Redis 数据全部存在内存,定期写入磁盘,当内存不够时,可以选择指定的 LRU 算法删除数据。
MongoDB 数据存在内存,由 linux系统 mmap 实现,当内存不够时,只将热点数据放入内存,其他数据存在磁盘。

从支持的数据结构来说:
Redis 支持的数据结构丰富,包括hash、set、list等。
MongoDB 数据结构比较单一,但是支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富。

缓存用redis而不用mongodb的主要是由缓存的特性决定的。缓存需要:

  1. 访问速度快
  2. 支持的存储方式要符合多方面的系统需要
  3. 要比单纯读数据库更加节约成本
  4. 能保存的数据量要够多

首先Redis完全符合上面我们说的几个特征,并且还是基于内存的,可持久化的数据库,并且是非常友好的Key-Value键值对的方式存储
而MongoDB数据库作为非结构化的文件数据接,其功能和特征并不能支持大多数的缓存数据的存放,只会徒劳增加成本
MongoDB的更多使用方式还是存储一些大的文件之类的数据,不是专注于去实现一些缓存数据的存储
Redis就不一样了,他本身就是应运而生的,除了做缓存数据库虽然还能实现消息队列之类的功能,但是那都是一些附属价值; Redis最核心的价值还是缓存数据库,多种数据结构,丰富的API使得Redis在目前的环境中暂时还找不到太多的对手

参考

  1. 人人都说好的Spring Cache!用起来! https://zhuanlan.zhihu.com/p/452315531
  2. 为什么用MongoDB而不用Redis https://blog.csdn.net/xingjing1226/article/details/89096696
  3. spring 缓存中@Cacheable、@CachePut和@CacheEvict介绍 以及#p0的含义 https://blog.csdn.net/qq_29663071/article/details/81511845
  4. 缓存为什么要用 Redis,而不是使用 MongoDB https://blog.csdn.net/to_real/article/details/122085687
0
  • 0
  • 1

评论区