今天来看一下SpringBoot的内置缓存CacheManager怎么使用!
直接上代码:
一、先建立个dao层模仿查询数据库:
packagecom.xing.studyboot.rest.dao.impl; importorg.springframework.stereotype.Service; importcom.xing.studyboot.rest.dao.CommonDao; publicclassCommonDaoImplimplementsCommonDao { publicStringget() { return"ok!奥里给"; } }
二、建个Service调用dao
"cache") (publicStringgetCache() { System.out.println("调用getCache开始"); Stringres=commonDao.get(); System.out.println("调用getCache结束"+res); returnres; }
三、在Controller中发布一个接口来访问
packagecom.xing.studyboot.rest.controller; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RestController; importcom.xing.studyboot.rest.service.CommonService; "/cache") (publicclassCacheController { CommonServicecommonService; "/get") (publicStringgetName() { Stringres=commonService.getCache(); return"缓存-》"+res; } }
四、在启动类添加@EnableCaching注解来启用缓存
packagecom.xing.studyboot; importorg.springframework.boot.SpringApplication; importorg.springframework.boot.autoconfigure.SpringBootApplication; importorg.springframework.cache.annotation.EnableCaching; importcom.xing.studyboot.config.MyBanner; publicclassStudybootApplication { publicstaticvoidmain(String[] args) { SpringApplicationspringApplication=newSpringApplication(StudybootApplication.class); springApplication.run(args); } }
访问一下:
第一次访问,发现控制台打印调用了Service中的方法,输出了开始结束过程。再次刷新访问,发现并没有继续输出,但是页面却正常的返回了数据。说明缓存使用成功了!
我重新启动服务,发现缓存竟然没有消失,同样没有执行Service中的方法就返回了数据,我们来添加一个配置类来指定一下缓存的存储位置:
packagecom.xing.studyboot.config.redis; importjava.util.Arrays; importorg.springframework.cache.CacheManager; importorg.springframework.cache.concurrent.ConcurrentMapCache; importorg.springframework.cache.support.SimpleCacheManager; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; /*** 配置一个简单的缓存,指定缓存位置* @author xing* @createTime*/publicclassCacheManagerConfig { publicCacheManagercacheManager() { SimpleCacheManagercacheManager=newSimpleCacheManager(); cacheManager.setCaches(Arrays.asList(newConcurrentMapCache("sampleCacheTest"))); cacheManager.afterPropertiesSet(); returncacheManager; } }
现在指定缓存到一个叫 sampleCacheTest 的ConcurrentMapCache对象中,再次访问突然报错,原来是在方法上的@Cacheable("sampleCacheTest")注解,这里应该指定存到sampleCacheTest 。
这样每次重新启动后,就会清空sampleCacheTest 对象中的缓存啦。
打开注解源码发现很多熟悉的东西哈:
搜了点几个注解的说明:
1.CacheManager管理多个Cache组件的,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字cacheNames/value: 指定缓存组件的名字(缓存到哪个缓存组件中)key:缓存数据使用的key;可以用它来指定。默认是使用方法参数的值,1-方法的返回值编写SpEl;#id;参数id的值#a0#p0#root.args[0] keyGenerator:key的生成器;可以自己指定key的生成器的组件id(可以自定义一个KeyGenerator,然后注册到容器中)(下一篇运行流程原理会测试)key/keyGenerator:二选一使用cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器(后面单独有一篇写这个的)condition:指定符合条件的情况下才缓存condition="#id > 1":id大于1才进行缓存unless:否定缓存/排除条件;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果并进行判断unless="#result == null"unless="#id == 2" : id等于2就不缓存(如果满足condition也满足unless,以unless的为准)sync:是否同步;在多线程环境下,某些操作可能使用相同参数同步调用。默认情况下(默认不同步,也就是异步),缓存不锁定任何资源,可能导致多次计算,而违反了缓存的目的。对于这些特定的情况,属性sync可以指示底层将缓存锁住,使只有一个线程可以进入计算,而其他线程堵塞,直到返回结果更新到缓存中。2.先调用目标方法(目标方法一定会被执行)将方法的返回值存到缓存中3.删除缓存中的数据key:指定要删除的keyallEntries:是否删除该缓存组件中的所有缓存(默认false)beforeInvocation:是否在目标方法执行之前清除缓存默认false:在目标方法执行之后清除缓存;如果目标方法执行时出错了就不会清除缓存了beforeInvocation=true:在目标方法执行之前清除缓存;不管目标方法出错与否都会清除缓存4.属性是缓存注解的集合,因此可以配置复杂的缓存配置例如: ( cacheable= { cacheNames="emp", key="#lastName") ( }, put= { cacheNames="emp", key="#result.id") ( } ) 5.CacheConfig标注在类上,抽取每个方法中相同的属性,这里只要定义一次就ok,以cacheNames为例cacheNames="emp") (publicclassEmployeeService {}
总结:
项目中一般都使用缓存中间件,比如redis等。
END