Spring之路(49)–Spring缓存性能提升如升天?但你真的用对了吗?
2020/2/21 8:25:30
本文主要是介绍Spring之路(49)–Spring缓存性能提升如升天?但你真的用对了吗?,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
背景
Spring缓存,用了确实爽,性能的提升就像俺升天了那么爽快,但是如果理解不够深,不够准确的话,会带来灾难性的问题。
比如该使用缓存的时候,实际上并没有使用缓存,这种情况,相当于缓存无效。
比如不该使用缓存的时候,缓存却跳出来了,这种情况就可怕了,意味着你拿到了不该拿的数据。
所以本文就以实际的例子,演示下Spring缓存中那些需要注意的点。
同一缓存下,只看参数不看方法名
如下面的例子
@Cacheable("blogs") public List<BlogDo> getListAsc() { System.out.println("升序获取blog列表"); return null; } @Cacheable("blogs") public List<BlogDo> getListDesc() { System.out.println("降序获取blog列表"); return null; }
本意是想有两个缓存,分别缓存升序的blog列表和降序的blog列表,但是由于这两个方法都是使用的名为blogs的缓存,且都没有参数,导致第二个方法会将第一个方法执行的缓存取出来:
public static void main(String[] args) throws SQLException { // 获取容器 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); // 获取blogService组件 BlogService blogService = context.getBean("blogService", BlogService.class); //输出:升序获取blog列表 blogService.getListAsc(); //没有输出,因为直接取缓存了 blogService.getListDesc(); }
那么这种情况该如何处理呢,有以下几种处理办法:
- 改为不同的缓存名称,比如一个用
@Cacheable("blogsAsc")
,另一个用@Cacheable("blogsDesc")
。这种方法十分不推荐,因为都是面向的blog这个表,用了两个缓存,那么清除缓存的时候咋办?很麻烦! - 使用参数区分,加一个枚举类型表示升序和降序,方法改为
getListAsc(SortEnum.ASC)
和getListAsc(SortEnum.ASC)
。这种方法也不推荐,因为太麻烦了。 - 推荐方法是:既然都是取的博客列表,直接定义一个
getList
方法即可,然后对该方法添加缓存。至于排序的事情,自己取出结果后排序就是了。
缓存方法调用判断的是对象相等,而不是数值相等
如下面的例子:
@Cacheable("blogs") public Long getLong(Long a) { System.out.println("getLong"); return a+1; } @Cacheable("blogs") public Integer getInteger(Integer a) { System.out.println("getInteger"); return a+2; }
感觉上,如果都是对数字1进行查询,应该能触发缓存,实际上并没有,就是因为这两个对象并不相等
public class Main { public static void main(String[] args) throws SQLException { // 获取容器 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); // 获取blogService组件 BlogService blogService = context.getBean("blogService", BlogService.class); //测试 blogService.getLong(1L);// 输出getLong blogService.getLong(1L);// 没有输出,因为已经有缓存 blogService.getInteger(1);// 输出getInteger因为参数并不相等 Integer a = 1; Long b = 1L; System.out.println(a.equals(b));// 输出false,证明这两个参数实际上不相等 } }
如果参数是对象,一定要实现.equals和hashcode
在上面我们已经说明了,缓存参数的触发,是按对象是否相等来实现的,如果没有实现.equals和hashcode,就会出现:
BlogDo blog1=new BlogDo(); blog1.setId(1L); blogService.getByObject(blog1); blogService.getByObject(blog1);//触发缓存 BlogDo blog2=new BlogDo(); blog2.setId(1L); blogService.getByObject(blog2);//没触发缓存,因为blog1与blog2不同
注意,因为是map结构,务必要同时实现.equals和hashcode
,否则判断也不准确!
总结
如果感觉还不清楚的话,还可以在调试模式下去查看CacheManager的具体内容,如下:
// 获取容器 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); // 获取blogService组件 BlogService blogService = context.getBean("blogService", BlogService.class); //测试 blogService.getLong(1L);// 输出getLong blogService.getLong(1L);// 没有输出,因为已经有缓存 blogService.getInteger(1);// 输出getInteger因为参数并不相等 //查看缓存 CacheManager cacheManager=context.getBean("cacheManager", CacheManager.class);
此时我们查看缓存中的内容就好理解了,此处感兴趣的可以自己去试下,我不再详细分析了。
这篇关于Spring之路(49)–Spring缓存性能提升如升天?但你真的用对了吗?的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?
- 2024-05-09企业src漏洞挖掘-有意思的命令执行
- 2024-05-08阿里云域名注册流程,分享给第一次购买域名的新手站长!