50

springboot基础01 – 缓存的使用

 4 years ago
source link: https://www.tuicool.com/articles/6rQrueE
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前两天解决了一个Spring缓存的问题,因此就想到记录一下spring-boot缓存的使用。

开启缓存

SpringBoot开启缓存也容易,在启动类上添加 @ EnableCaching 注解就可以了,不需要过多的配置。此时开启的缓存是比较简单的缓存,即基于ConcurrentHashMap实现的缓存。虽然简单,但对于负载不高的应用也足够用了。

SpringBoot缓存两个关键类是: CacheAutoConfiguration CacheAspectSupport 。这两个类分别位于spring-boot-autoconfigure和spring-context包。也就是说不使用 spring-boot-starter-cache 包也能在spring-boot中使用简单的缓存。

CacheType 类中可以看到SpringBoot支持的缓存类型。懒得一个一个介绍了,直接看下代码好了:

public enum CacheType {
 
	/**
	 * Generic caching using 'Cache' beans from the context.
	 */
	GENERIC,
 
	/**
	 * JCache (JSR-107) backed caching.
	 */
	JCACHE,
 
	/**
	 * EhCache backed caching.
	 */
	EHCACHE,
 
	/**
	 * Hazelcast backed caching.
	 */
	HAZELCAST,
 
	/**
	 * Infinispan backed caching.
	 */
	INFINISPAN,
 
	/**
	 * Couchbase backed caching.
	 */
	COUCHBASE,
 
	/**
	 * Redis backed caching.
	 */
	REDIS,
 
	/**
	 * Caffeine backed caching.
	 */
	CAFFEINE,
 
	/**
	 * Simple in-memory caching.
	 */
	SIMPLE,
 
	/**
	 * No caching.
	 */
	NONE
 
}

可以看到,支持了差不多所有的主流缓存。

缓存注解

spring boot的缓存主要是由注解支持实现的。下面是几个常见的注解:

  • @ Cacheable :针对方法进行配置,根据方法的请求参数缓存返回值,如无缓存值则执行方法;
  • @ CacheEvict :用于移除缓存记录,调用方法时会执行移除操作;
  • @ CachePut :用于更新缓存记录;保证方法一定会被调用,同时缓存方法返回值;与@Cacheable的区别在于是否每次都调用方法;
  • @ CacheConfig :统一配置管理类内部所有缓存注解的属性。

@ Cacheable @ CachePut 注解属性说明

  • keyGenerator:缓存数据key生成策略;
  • CacheManager:缓存管理器,管理缓存组件;
  • CacheResolver:缓存解析器,根据实际情况动态解析决定使用哪个缓存实例;
  • value:缓存实例(一个缓存实例可以存储多个缓存KV对)的名称,至少需要设置一个;
  • key:缓存的 key,如果不为空需要要按照 SpEL 表达式编写;如果不为空则缺省按照方法的所有参数进行组合;
  • condition:缓存条件,使用 SpEL 编写;若不为空,只在条件结果为 true 时才进行缓存;
  • unless:缓存排除条件,当条件结果为TRUE时不会缓存;
  • sync:是否同步操作,如为true,那么多个线程访问同一条记录时,会同步执行调用的方法。

@ CacheEvict 注解属性说明

@ CacheEvict 注解的属性大致同 @ Cacheable 一致,不过 @ CacheEvict 还有两个独有的属性:

  • allEntries:是否清空所有缓存内容,缺省为 false;如果指定为 true,则方法调用后将立即清空所有缓存;
  • beforeInvocation:是否在方法执行前就清空,缺省为 false;如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存。

@ CacheConfig 注解属性说明

@ CacheConfig 注解的属性 @ Cacheable 都有。因为 @ CacheConfig 注解的作用本来就是统一管理相同类下所有方法的缓存配置。

需要提一下的就是在spring4.1之前是没有 @ CacheConfig 注解的,那时候需要在每个方法的 @ Cacheable 注解中设置 cacheNames 属性。

SpEL表达式

下面简单介绍下SpEL表达式的语法——看下表的,摘自Spring官方文档:

名称 位置 描述 示例 methodName root对象 当前被调用的方法名 #root.methodname method root对象 当前被调用的方法 # root.method.name target root对象 当前被调用的目标对象实例 #root.target targetClass root对象 当前被调用的目标对象的类 #root.targetClass args root对象 当前被调用的方法的参数列表 #root.args[0] caches root对象 当前方法调用使用的缓存列表 #root.caches[0].name Argument Name 执行上下文 当前被调用的方法的参数,如findArtisan(Artisan artisan),可以通过#artsian.id获得参数 # artsian.id result 执行上下文 方法执行后的返回值(仅当方法执行后的判断有效,如 unless cacheEvict的beforeInvocation=false) #result

注意事项:

  1. 当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性, 如 @ Cacheable ( key = "targetClass + methodName +#p0" ) ;
  2. 使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”,如: @ Cacheable ( value = "users" , key = "#id" ) @ Cacheable ( value = "users" , key = "#p0" )
类型 运算符 关系 <,>,<=,>=,==,!=,lt,gt,le,ge,eq,ne 算术 +,- ,* ,/,%,^ 逻辑 &&,||,!,and,or,not,between,instanceof 条件 ?: (ternary),?: (elvis) 正则表达式 matches 其他类型 ?.,?[…],![…],^[…],$[…]

使用Caffeine缓存

前面的配置,即只在在启动类上添加 @ EnableCaching 注解的情形下,我们只能使用最基础的 SIMPLE 缓存。现在我们需要尝试使用Caffeine缓存,就需要再多做些配置了。

在做这个配置的时候遇到了些问题,所以在这里也简单记录下解决问题的过程。

首先,需要在配置文件中指明使用Caffine缓存并添加Caffeine缓存的配置:

spring:
  cache:
    type: CAFFEINE
    caffeine:
      spec: initialCapacity=1048576,maximumSize=1073741824,expireAfterAccess=10m

然后加入Caffeine缓存依赖:

        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </dependency>

然而此时调用方法会发现启动失败,报错如下:

Caused by: java.lang.IllegalArgumentException: No cache manager could be auto-configured, check your configuration (caching type is 'CAFFEINE')
	at org.springframework.util.Assert.notNull(Assert.java:215)
	at org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration$CacheManagerValidator.afterPropertiesSet(CacheAutoConfiguration.java:107)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774)
	... 42 common frames omitted

提示缺少CacheManager,说实话一开始看到这个错误提示我是不知咋回事儿的。

将spring-boot的debug配置设置为true,再重新执行,会有如下提示:

   CaffeineCacheConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'com.github.benmanes.caffeine.cache.Caffeine', 'org.springframework.cache.caffeine.CaffeineCacheManager' (OnClassCondition)

提示Caffeine缓存的自动配置需要两个类 com . github . benmanes . caffeine . cache . Caffeine org . springframework . cache . caffeine . CaffeineCacheManager 。前者在引入caffeine的jar以后已经不是问题,后者则需要引入新的依赖。

CaffeineCacheManager 这个类位于spring-context-support中,我们可以直接引入这个依赖,不过更推荐通过spring-boot-starter-cache来间接引入,这样指向性会更明确一些。

spring-boot-starter-cache依赖如下:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

添加spring-boot-starter-cache依赖后再次测试,应用启动正常,缓存正常。

如需引入其他类型的缓存,也可以按类似的步骤来进行配置。

就这样。写了个示例应用,放在github了,有需要可以看一下: spring-boot-cache

噢,对了,Caffeine缓存在spring-boot下有个坑,以前踩到过,记录在这里了: 《spring caffeine缓存慎用weakKeys》


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK