今天介绍如何使用springboot的注解来缓存一个Object 或者一个List 列表。
1: 引入 maven 依赖 使用 springboot 2.1.3.RELEASE
net.sf.ehcache ehcache org.springframework.boot spring-boot-starter-cache
2: 配置使用 ehcache
spring.cache.type=ehcachespring.cache.ehcache.config=classpath:/ehcache.xml
3: 配置 ehcache
在项目的根目录添加 ehcache.xml ,
4: springboot 开启缓存注解的功能。
5: 使用 @Cacheable 进行缓存, 将搜索列表的结果缓存10分钟。
6: 如何测试缓存生效了? 在方法中打一个断点, 第一次访问触发到断点了, 第二次访问没有触发断点, 两分钟后再访问又触发了断点。
7: 如何更新缓存? 数据库的数据会有增加,删除和修改, 会导致和缓存中的数据不一致.
从A机器搜索关键词可能命中10条记录,但由于数据库变更会导致下次在B 机器上搜索相同的关键词可能命中11条数据。 A 和 B 两台机器上的缓存不一致。 还有就是删除记录就是 10分之后才会删除,如果能忍受这些。
8:缓存的效率问题
1: 如果2分钟之内这个列表只被访问1次,那么这个缓存就是个累赘,白白消耗内存。 因此缓存的列表一定得是高频使访问的。
2:重复缓存的问题。 假设2分钟内有效的搜索词为n, 每次搜索用户会点击前两页 ,那么会产生 2n个 list, 2n * 10 个 Object, 其中有些Object 必定是被多次重复缓存的。
9: Redis 和 Ehcache 之争。 如果网站本身没有多少并发访问的使用Ehcache ,甚至可以不使用缓存,只要数据库能抗, 数据库扛不住加Ehcache, Ehcache 扛不住再想其他办法, 如果到了Ehcache 都扛不住那就是这个网站已经比较成功了,可以考虑请个高人进行开发。
10 : spring缓存和Hibernate缓存
网上一般介绍 Hibernate 缓存有两级缓存 1 : 一级缓存, session 级别的缓存 2: 二级缓存 factory 层级的缓存,亦称进程级别或者应用级别的缓存。 个人理解 springboot的缓存是可以完全替代Hibernate的二级缓存的。
总结 springboot 的骚操作比较多,比较简单, 相比于spring 复杂的xml 配置, springboot 的配置则大大简化,更加易于初级程序员上手使用,从而提高了开发的效率和质量,减少了程序员的代码量。 Pivotal 是一家纯粹靠技术起家的公司。
原理分析: debug 跟踪堆栈信息是比较靠谱的逆向分析方法。 顺向思维就是去看源码,读懂源码的每一步操作,但是读懂源码却是十分十分的困难,难于上青天。
堆栈信息如下:
先是执行了 AreaController$$EnhancerBySpringCGLIB 的 getContent 方法 , 此getContent 是重写了 AreaController 的getContent 方法,
然后执行了一些列的拦截器
CglibAopProxy$DynamicAdvisedInterceptor ---> ExposeInvocationInterceptor --------------->DruidStatInterceptor ------------> CacheInterceptor ------> AreaController$$FastClassBySpringCGLIB
执行了这么多才会调用我们写的 method getContent 。
具体的实现在 CacheAspectSupport 类里面 。
在这里也能略微体会到 filter 和 interceptor 的区别。
filter01--------->filter02--------> filter03 -----> controller(method)-----------> response filter 是单向的执行,无法获取到method的返回值。
interceptor01 ------> interceptor02 --------> controller(method) -------> interceptor02 --------->interceptor01
interceptor 的执行却类似一个U, 是可以获取到method的返回值的。 filter 能干的事 interceptor 一定能干, 并且interceptor 可以干 filter 干不了的事。
关于chain , 责任链是一种JAVA 设计模式。 在我所接触的软件中,我知道这些地方使用到了责任链模式。
1: tomcat 的 Value 链
网上分析的文章不多,毕竟研究servlet容器的工程师少,只有那些闲得无聊的人才会去看servlet容器是如何运转的。 这篇博客也有提及
2: Servlet 的 FilterChain
相信从事过javaweb 开始的工程师都应该了解这个,网上关于过滤链的分析非常多。
3: 再加上 spring 的 拦截器链。
AreaController$$EnhancerBySpringCGLIB 和 AreaController$$FastClassBySpringCGLIB 值得分析一下,前者是spring 的大BOSS,我们写的Controller , Service ,Repository 都被 EnhancerBySpringCGLIB 代理了。 有了这层代理后, spring 在执行我们写的方法的前后植入了相关的功能,执行之前先执行拦截器,执行之后执行渲染操作。