作者回复: 它们是不一样的,spring.cache.cache-names=coffee,是用来配置默认缓存的,启动时会把其中指定的缓存创建出来,运行时的缓存不能超出我这指定的范围(有同学反馈这个与底层的缓存实现有关,因此补充一下,比如Simple的不能超过,但Redis的可以),不配的话就看代码里用到哪些动态创建。@CacheConfig用来配置类级别共享的缓存配置,配置不在@CacheConfig里,就需要加在@Cacheable里。
作者回复: 你是说你没有配置proxyTargetClass,所以Spring用了默认的false?事实上,虽然你没有配置,但Spring Boot替你配了,你可以DEBUG一下看看你的Bean是不是被CGLIB增强了,即使你最后想尽一切办法设置成了false,Spring在判断你的Bean没有实现任何接口后,还是会给你设置为true,详见ProxyProcessorSupport.evaluateProxyInterfaces中有一行proxyFactory.setProxyTargetClass(true)。去年还有人给Spring Boot提过类似的issue,https://github.com/spring-projects/spring-boot/issues/12194 。
作者回复: Spring基于Java接口的动态代理要求你的目标类得要实现接口,动态代理出来的类也是这个接口的实现,但往往很多时候,我们的类是没有实现什么接口的,故意去写一个接口也挺繁琐的,所以proxy-target-class让我们可以直接对类做代理。
作者回复: Spring Boot会根据Classpath里的内容自动来判断的,有Redis相关类和配置时会用Redis。你可以用spring.cache.type来指定类型
作者回复: 如果是默认的,那就在JVM里,如果你用的是Redis的缓存,那就存在Redis里,缓存就是用空间换时间。如果是放在Redis里的,Value很大就会带来一定的反序列化开销,Redis本身对大Key操作也有开销,尽量不要太大。另外,一定要设置过期时间,哪怕你的东西不变,可以设置一个比较长的时间,后面续期,也不要不设,除非你很确定,你就是永久的。
作者回复: 就是个string,你取不到是因为代码里设置了个比较短的过期时间5000,一下子就过期了,你把这个值设长点,然后就能看到了。
作者回复: 堆里缓存的东西多,年老代被占用的空间就会多,如果本身你的系统还是大量使用内存的,就会有点吃力,GC会变得频繁等等的。你可以计算一下,缓存的数据大概有多少MB,如果很大,可以设置LRU策略,并不用把所有的内容都放在JVM里,可以结合JVM和Redis,JVM内部没命中的,再访问Redis,替换掉很久没用的缓存。仅供参考。
作者回复: 默认Spring会用序列化的方式来做转换,你可以设置大家都序列化成JSON,后面的课程的例子里我们会讲到怎么设置Redis的序列化和反序列化方式。
作者回复: 可以看下CompositeCacheManager,这里可以组合多个CacheManager,每个都能用不同的配置
作者回复: 这个注解缓存的是方法的结果,不管方法里是做什么的。