springboot+mybatis + 缓存, 基本的用法想必是会了, 现在说一说内部大概的原理.
稍微提一下 mybatis, 只要导入了 mybatis 的依赖, 那么有个自动配置类就会生效, 你可以去 mybatis 的 jar 包里面的 META-INF/spring.factories 中看到这个 xxxAutoConfiguration, 就如下图所示, 这个应该很熟悉了, 所以我们要看看 mybatis 的配置, 肯定要看这个类.
开这个类, 看到这里
看了看, 其他的没什么说的, 要看看在 YAML 给 mybatis 可以配置哪些参数, 就去这个类 MybatisProperties 看看有哪些属性就 ok 了, 用起来也是很容易.
接下来看看比较有趣的地方, 看看缓存的原理.
缓存原理
肯定又是自动配置类, ctrl+N 搜索一个 CacheAutoConfiguration
我们要看看这个 @Import 导入了什么组件, 点开这个类, 打个断点调试一下
调试之后可以看到就是加载了一些 xxxCacheConfiguration, 有没有发现其中有一个是 EnCacheCacheConfiguration, 还有一个是 RedisCacheConfiguration, 不就是 encache 缓存, Redis 缓存嘛! 即使没用过, 名字应该听过吧, 所以我们大概猜想一下, 这是不是 springboot 提供的针对每个做缓存的公司做出来产品的配置类, 只要我们导入相关的依赖, 这些配置类就能够生效?
可以测试一下我们用的是哪一个, 在 YAML 文件中, 加入一个配置 debug:true, 然后启动应用, 可以看到所有配置类的打印日志
下图所示, 说明默认的是用这个缓存配置类, 当然你还可以看看其他的缓存配置类没有生效
说明 springboot 默认用的缓存配置类是 SimpleCacheConfiguration, 那我们来看看加载成功的这个缓存配置类, 只要弄清楚这个, 其他的肯定都差不多
打开 SimpleCacheConfiguration 这个类
我们看看缓存管理器里有什么;
回忆一下我上节说的, CacheManager 负责哪个缓存公司做的产品, Cache 表示这个缓存产品里面很多小空间并且我们要为它取个名字(从下图看, 其实就是名字代表 String, 小空间就是 Cache), 而我们要存的键值对就是放在小空间里(Cache), 由此可以大概推出 Cache 里面就是存放键值对的(潜台词就是 Cache 就是一个 map)
ok, 其实现在我们已经推断出来了所谓的缓存就是一个 map, 这个 map 里又嵌套了一个 map, 类似这样的 Map<String,Map<key,value>>结构, 接下来, 我们继续看看源码(后面我所说的缓存其实对应这里就是 Map<key,value>, 这个东西等价于我前面提到的 Cache, 小空间).
我们还可以看看是怎么根据 key 找到值, 还有怎么将方法的返回值丢到缓存里去
看到这里, 不知道大家是否大概对缓存有了一个本质的了解了, 不要把缓存想得多么复杂, 说破天了不就是一个 map 嘛!
其实那些缓存公司提供给我们用的就是一个 Map<String,Map<key,value>>, 其中通过很牛的算法, 让我们用起来很流畅的这么一个东西. 而且, 我们用缓存的话, 肯定要先指定那个 String 啊 (可以指定多个哦, 比如 @Cacheable(cacheName={"name1","name2"}), 不要不会用 map 了!!!), 然后就是通过 key(默认就是用方法里的参数作为 key) 去找到对应的 value, 这个 value 就是我们第二次以及之后查询需要从从缓存里拿到的数据.
我应该说的比较详细了, 我大概总结一下: 启动 springboot-------->容器里没有缓存管理器, CacheAutoConfiguration 才起作用 ---------->自动配置类有个注解 @Import, 导入了一个 xxxSelector, 这个 xxxSelector 向容器里导入很多的缓存配置类 (其实默认起作用的就是 SimpleCacheConfiguration)------------>SimpleCacheConfiguration 配置类中向容器里丢进去一个缓存管理器 --------------> 这个缓存管理器内部其实就是一个 Map<String,Cache>----------->第一次根据 String 去获取 Cache,Cache 为 null, 创建一个 Cache,Cache 是一个 Map<key,value>----------------->执行 service 中的方法, 返回值放进去这个 Map<key,value > 中, 其中 key 是 service 内方法的形参 (这里注意, 后面我会说一说怎么将形参按照一定的规则包装成一个 key 的)--------------> 第二次查询, 首先根据 String 去找到对应的 Cache, 返回 Cache, 然后根据形参生成一个 key, 到上面的 lookup 方法去拿到数据, 返回, 结束.
小知识补充:
前面一直说按照一定的规则生成 key, 但是具体什么规则呢? 我们就来看看.
第一种: 我们自己指定的例如 @Cacheable(key="#id"), 就是指定形参 id 作为 key, 这里支持 sSpEL 表达式, 假如方法的返回值是对象 student, 可以写成 @Cacheable(key="#result.id"), 这是也是将返回结果的 id 作为 key, 具体的 SpEL 表达式可以自己查查资料学习.
第二种: springboot 默认的, 我们在哪里看呢?
使用断点调试
假如有兴趣自己去调试的小伙伴, 可以参照一下我调试的位置, 我把我调试的断点位置放出来:
断点位置
等到找到下图这个方法
ok, 这断点位置就是这几个, 调试启动 springboot, 在浏览器输入 url, 就会自己进入调试界面, 你就慢慢点就 ok 了.
本来还要说点东西的, emmmm.... 篇幅太长了, 估计还要往后拖了....
来源: https://www.cnblogs.com/wyq1995/p/10022084.html