使用spring cache让我的接口性能瞬间提升了100倍( 二 )

3.使用Cacheable注解获取数据
@Servicepublic class CategoryService {//category是缓存名称,#type是具体的key,可支持el表达式@Cacheable(value = https://www.isolves.com/it/cxkf/kj/2020-09-27/"category", key = "#type")public CategoryModel getCategory(Integer type) {return getCategoryByType(type);}private CategoryModel getCategoryByType(Integer type) {System.out.println("根据不同的type:" + type + "获取不同的分类数据");CategoryModel categoryModel = new CategoryModel();categoryModel.setId(1L);categoryModel.setParentId(0L);categoryModel.setName("电器");categoryModel.setLevel(3);return categoryModel;}}4.测试
@Api(tags = "category", description = "分类相关接口")@RestController@RequestMapping("/category")public class CategoryController {@Autowiredprivate CategoryService categoryService;@GetMapping("/getCategory")public CategoryModel getCategory(@RequestParam("type") Integer type) {return categoryService.getCategory(type);}}在浏览器中调用接口:

使用spring cache让我的接口性能瞬间提升了100倍

文章插图
 
可以看到,有数据返回 。
再看看控制台的打印 。
使用spring cache让我的接口性能瞬间提升了100倍

文章插图
 
有数据打印,说明第一次请求进入了categoryService.getCategory方法的内部 。
然后再重新请求一次,
使用spring cache让我的接口性能瞬间提升了100倍

文章插图
 
还是有数据,返回 。但是控制台没有重新打印新数据,还是以前的数据,说明这一次请求走的是缓存,没有进入categoryService.getCategory方法的内部 。在5分钟以内,再重复请求该接口,一直都是直接从缓存中获取数据 。
使用spring cache让我的接口性能瞬间提升了100倍

文章插图
 
说明缓存生效了,下面我介绍一下spring cache的工作原理
三、工作原理 
通过上面的例子,相当朋友们对spring cache在项目中的用法有了一定的认识 。那么它的工作原理是什么呢?
相信聪明的朋友们,肯定会想到,它用了AOP 。
 
没错,它就是用了AOP 。那么具体是怎么用的?
 
我们先看看EnableCaching注解
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(CachingConfigurationSelector.class)public @interface EnableCaching {// false JDK动态代理 true cglib代理boolean proxyTargetClass() default false;//通知模式 JDK动态代理 或 AspectJAdviceMode mode() default AdviceMode.PROXY;//排序int order() default Ordered.LOWEST_PRECEDENCE;} 
这个数据很简单,定义了代理相关参数,引入了CachingConfigurationSelector类 。再看看该类的getProxyImports方法
private String[] getProxyImports() {List<String> result = new ArrayList<>(3);result.add(AutoProxyRegistrar.class.getName());result.add(ProxyCachingConfiguration.class.getName());if (jsr107Present && jcacheImplPresent) {result.add(PROXY_JCACHE_CONFIGURATION_CLASS);}return StringUtils.toStringArray(result);}该方法引入了AutoProxyRegistrar和ProxyCachingConfiguration两个类
 
AutoProxyRegistrar是让spring cache拥有AOP的能力(至于如何拥有AOP的能力,这个是单独的话题,感兴趣的朋友可以自己阅读一下源码 。或者关注一下我的公众账号,后面会有专门AOP的专题) 。
 
重点看看ProxyCachingConfiguration
@Configuration@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public class ProxyCachingConfiguration extends AbstractCachingConfiguration {@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor() {BeanFactoryCacheOperationSourceAdvisor advisor = new BeanFactoryCacheOperationSourceAdvisor();advisor.setCacheOperationSource(cacheOperationSource());advisor.setAdvice(cacheInterceptor());if (this.enableCaching != null) {advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));}return advisor;}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public CacheOperationSource cacheOperationSource() {return new AnnotationCacheOperationSource();}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public CacheInterceptor cacheInterceptor() {CacheInterceptor interceptor = new CacheInterceptor();interceptor.setCacheOperationSources(cacheOperationSource());if (this.cacheResolver != null) {interceptor.setCacheResolver(this.cacheResolver);}else if (this.cacheManager != null) {interceptor.setCacheManager(this.cacheManager);}if (this.keyGenerator != null) {interceptor.setKeyGenerator(this.keyGenerator);}if (this.errorHandler != null) {interceptor.setErrorHandler(this.errorHandler);}return interceptor;}}


推荐阅读