怎么在Spring中对抽象进行缓存
怎么在Spring中对抽象进行缓存?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
Spring缓存抽象概述
Spring框架自身并没有实现缓存解决方案,但是从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口,提供对缓存功能的声明,能够与多种流行的缓存实现集成。
Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;
Cache接口下Spring提供了各种xxxCache的实现:如RedisCache,EhCacheCache , ConcurrentMapCache等;
CacheManager接口为缓存管理器规范,简单来说就是用于存放cache,Spring默认也提供了一些列管理器的实现。
Spring缓存抽象提供了5个注解用来声明缓存规则:
@Cacheable:能够根据方法的请求参数对其结果进行缓存,多用于查询
@CachePut: 执行方法,并缓存结果
@CacheEvict:清空缓存
@Caching:能够同时应用多个缓存注解功能
@CacheConfig: 用于抽取缓存的公共配置(类级别)
以上5个注解除了@CacheConfig注解是类级别的注解,其余4个注解在类和方法上均可以使用,作用在类上表示对该类下所有方法生效,作用的方法上只对该方法生效,且只能用于public修饰的符方法,protected或者private修饰的方法不适用。
@Cacheable注解
@Cacheable注解的作用是Spring在调用该方法之前,首先在缓存中查找方法的返回值,默认的key是根据参数值生成,如果存在,直接返回缓存中的值,否则执行该方法,并将返回值保存到缓存中
@Cacheable运行流程:
1.方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;
(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。
2.去Cache中查找缓存的内容,使用一个key,默认就是方法的参数值;
key是按照某种策略生成的;默认是使用keyGenerator生成的,
Spring默认加载的是SimpleCacheManage,SimpleKeyGenerator生成key的默认策略是:
如果没有参数;key=new SimpleKey()
如果有一个参数:key=参数的值
如果有多个参数:key=new SimpleKey(params)
3.没有查到缓存就调用目标方法;
4.将目标方法返回的结果,放进缓存中
@Cacheable属性说明:
1.acheNames/value:该属性值必须提供,指定缓存组件的名字,将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;
如:cacheNames = "product"或者cacheNames = {"product1","product2"}
2.key:缓存数据使用的key,不指定key则默认是使用方法参数的值该属性值支持SpEL表达式
3.cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器
4.condition:指定符合条件的情况下才缓存
5.unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断
unless = "#result == null"
unless = "#a0==2":如果第一个参数的值是2,结果不缓存;
6.sync:是否使用异步模式
使用示例:
@Cacheable(cacheNames="product")//默认key为参数,多个参数SimpleKey[arg1,arg2] //@Cacheable(cacheNames="product",key="#root.methodName+'['+#id+']'") //@Cacheable(cacheNames="product",keyGenerator="myKeyGenerator") //@Cacheable(cacheNames="product",key="#root.methodName+'['+#id+']'",condition="#a0>10",unless="#a0==11")//带条件的缓存满足condition=true缓存,满足unless=true则不缓存 publicProductgetProductById(Longid){ Productproduct=productMapper.getProductById(id); System.out.println(product); returnproduct; } //指定key属性值 @Cacheable(cacheNames="product",key="#id")//”#+参数名”的形式,直接使用参数名 //或者 //@Cacheable(cacheNames="product",key="#a0")//”#a+参数位置”的形式 publicProductgetProductById(longid){ xxxx } @Cacheable(cacheNames="product",key="#productcondition.productId") //或者 //@Cacheable(cacheNames="product",key="#a0.productId") publicProductgetProduct(Productproductcondition){ xxxx }
自定义Key生成器
除了通过SPEL表达式之外,还可以通过自定义key生成器的方式,Spring缓存模块提供了org.springframework.cache.interceptor.KeyGenerator
接口用于缓存key的生成声明,因此我们可以自定义一个MyKeyGenerator类并实现了KeyGenerator接口 ,使用如下:
@Configuration publicclassMyCacheConfig{ @Bean("myKeyGenerator") publicKeyGeneratorkeyGenerator(){ returnnewKeyGenerator(){ @Override publicObjectgenerate(Objecttarget,Methodmethod,Object...params){ returnmethod.getName()+"["+Arrays.asList(params).toString()+"]"; } }; } }
该方法测试用,关于缓存key的生成方式,网上有很多种策略。
使用时只需要修改注解的key属性即可:
@Cacheable(cacheNames="product",keyGenerator="myKeyGenerator")
@CachePut
@CachePut注解的作用简单的说一句话:既调用方法,又缓存数据。@cachePut和@Cacheable两个注解都可以用于填充缓存,但使用上略有点差异,@Cacheable注解的执行流程是先在按key在缓存中查找,存在则返回,不存在则执行目标方法,并缓存目标方法的结果。而@CachePut并不会检查缓存,总是先执行目标方法,并将目标方法的结果保存到缓存中。实际中比如执行到更新操作时,则希望将最新的数据更新到缓存,如果该方法返回异常,将不再执行保存缓存的逻辑。
@CachePut属性说明
@CachePut注解属性与@CachePut类似,并没有增加其他属性
使用示例:
@CachePut(value="product",key="#result.productId",condition="#result!=null") publicProductupdateProduct(Productproduct){ intcount=productMapper.updateProduct(product); System.out.println("影响行数:"+count); if(count>0){ returnproduct; }else{ returnnull; } }
@CacheEvict注解
该注解的作用根据指定的key或者是allEntries属性值移除缓存中特性的键值对。
@CacheEvict属性说明
与@Cacheable相比@CacheEvict注解提供了另外两个属性:
1.allEntries:表示是否清空所有缓存内容,默认false,如果该值为true则清空指定cacheNames缓存块下所有内容,如果指定了allEntries为true,那么再zhidingkey值将没有意义
2.beforeInvocation:是否在执行方法前请空缓存,默认值为false,如果该值为true则在调用目标方法前执行清空缓存,为false的情况下,如果目标方法抛出异常,则不再执行清空缓存逻辑
示例:
//@CacheEvict(value="product",key="#id") //@CacheEvict(value="product",allEntries=true)//清楚所有缓存 @CacheEvict(value="product",allEntries=true,beforeInvocation=true)//清楚所有缓存 publicbooleandeleteProductById(Longid){ productMapper.deleteProductById(id); returntrue; }
@Caching注解
该注解是一个分组注解,作用是可以同时应用多个其他注解,该注解提供了3个属性cacheable,put,evict分别用于组合@Cacheable、@CachePut、@CacheEvict三个注解
使用示例:
@Caching( cacheable={@Cacheable(value="product",key="#productName")}, put={ @CachePut(value="product",key="#result.productId"), @CachePut(value="product",key="#result.productName") } ) publicProductgetProductByName(StringproductName){ Productproduct=productMapper.getProductByName(productName); returnproduct; }
当@Cacheing同时含有CachePut注解和Cacheable注解时,仍然会先执行目标方法。(并不是按@Cacheable的执行过程,先检查缓存,存在则返回)
@CacheConfig
是一个类级别的注解,允许共享缓存的名称、KeyGenerator、CacheManager 和CacheResolver
示例:
@Service @CacheConfig(cacheNames="product") publicclassProductService{ }
在类上使用该注解,指定cacheNames属性值,则类中方法上的注解将默认继承了该属性值,如果方法上注解使用和了@CacheConfig向同的属性,则以方法上的为准。
@Service @CacheConfig(cacheNames="product") publicclassProductService{ @Autowired privateProductMapperproductMapper; @Cacheable(cacheNames="product1",key="#root.methodName+'['+#id+']'") publicProductgetProductById(Longid){ Productproduct=productMapper.getProductById(id); System.out.println(product); returnproduct; } }
上面@Cacheable和@CacheConfig都指定了属性值cacaeNames,实际以方法上注解指定的为准。
Spring缓存抽象的关键原理就是使用spring AOP,通过切面实现了在方法调用前、调用后获取方法的入参和返回值,进而实现了缓存的逻辑。
看完上述内容,你们掌握怎么在Spring中对抽象进行缓存的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注恰卡编程网行业资讯频道,感谢各位的阅读!
推荐阅读
-
Spring框架基于注解开发CRUD详解
-
spring DI依赖注入方式和区别有哪些
-
spring data jpa开启批量插入、批量更新的示例分析
-
spring中怎么利用FactoryBean配置Bean
这篇文章将为大家详细讲解有关spring中怎么利用FactoryBean配置Bean,文章内容质量较高,因此小编分享给大家做个参考...
-
如何解决解决Spring Boot正常启动后访问Controller提示404的问题
小编给大家分享一下如何解决解决SpringBoot正常启动后访问Controller提示404的问题,希望大家阅读完这篇文章之后...
-
Spring中怎么解决循环依赖问题
本篇文章给大家分享的是有关Spring中怎么解决循环依赖问题,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有...
-
Spring(aop,如何通过获取代理对象实现事务切换)
Spring,aop,如何通过获取代理对象实现事务切换,恰卡网带你了解更多相关信息。Springaop获取代理对象实现...
-
Spring(bean,四种注入方式详解)
Spring,bean,四种注入方式详解,恰卡网带你了解更多相关信息。目录一、Set方式注入pojo层:1.xml文件t...
-
Spring(Cloud,如何保证微服务内安全)
-
Spring(Cloud,Config,使用本地配置文件方式)