Spring Cache缓存


缓存介绍

Spring3.1之后引入了基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(如EHCache 或者Redis),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种annotation,即能够达到缓存方法的返回对象的效果。

Spring的缓存技术还具备相当的灵活性,不仅能够使用 SpEL(Spring Expression Language)来定义缓存的key和各种condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存,例如Redis、EHCache集成。

Spring Cache位于spring-content中,如下图

Spring Cache涉及主要类

Spring定义了Cache和CacheManager两个基础接口类。

Cache

Cache接口提供了其他缓存技术实现的规范,包括缓存的各种操作,增加、删除、获取缓存等。Cache默认实现缓存如下,其中EhcacheRedisCache都为流行的Cache实现方法。

CacheManager

CacheManager是Spring提供的各种缓存技术抽象接口,通过它管理Spring框架内部默认实现的CacheManager,Spring框架内部默认实现的CacheManager如下

CacheResolver

CacheResolver解析器,用于根据实际情况来动态解析使用哪个Cache。

KeyGenerator

KeyGenerator当使用注解时,默认key的生成规则。

Spring Cache主要的注解

@Cacheable

用于读取缓存的方法上,先从缓存中读取数据,如果没有再调用具体方法获取数据,然后将数据添加到缓存中。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Cacheable {
//cacheNames的别名
    @AliasFor("cacheNames")
    String[] value() default {};
//方法调用的结果存储时的cache名字
    @AliasFor("value")
    String[] cacheNames() default {};
//缓存的键值名称,支持SpEL
    String key() default "";
//key的生成策略
    String keyGenerator() default "";
//cache管理器,不指定使用默认
    String cacheManager() default "";
//cache解析器,不指定使用默认
    String cacheResolver() default "";
//满足何种条件才能被缓存,支持SpEL
    String condition() default "";
//满足哪些结果不加入缓存
    String unless() default "";
//是否同步读取缓存,更新缓存
    boolean sync() default false;
}

例子:

@Cacheable(value = "user", key = "#id",condition = "#id.length()>0",unless = "#id==null")
   public User findById(String id) {
       return userDao.findById(id).orElseGet(User::new);
   }

@CachePut

用于保存或者更新方法上,调用方法时将相应数据存入缓存中。

例子:

@CachePut(value = "user", key = "#user.id")
    @Transactional
    public User update(User user) {
        return userDao.save(user);
    }

@CacheEvict

用于删除方法上,删除对应缓存。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CacheEvict {
    ...
//是否删除所有实体对象
	boolean allEntries() default false;
//是否在方法调用之前执行,默认在调用方法执行成功后删除缓存。
	boolean beforeInvocation() default false;

例子:

@CacheEvict(value = "user")
   public void delete() {
       ...
   }

@Caching

组合使用Cache注解

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Caching {

	Cacheable[] cacheable() default {};

	CachePut[] put() default {};

	CacheEvict[] evict() default {};

}

@CacheConfig

全局Cache配置,自定义cache时需在方法上指定此注解。

@EnableCaching

开启Spring Cache的默认配置,启动缓存需要在项目中添加此注解。

Spring Boot集成

redis

支持分布式缓存,默认使用Luttuce客户端,也可采用Jedis。

引入依赖

pom.xml

<!--缓存-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--redis实现-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置文件

application.yml

单机模式配置

spring:
  application:
    name: coding-cache-redis
# redis配置    
  redis:
    host: localhost
    port: 6379
    password: 1111
    database: 0
# 启动缓存类型   
  cache:
    type: redis

哨兵模式配置

spring:
  application:
    name: coding-cache-redis
  redis:
    sentinel:
      master: mymaster
      nodes: 192.168.81.10:26375,192.168.81.11:26376,192.168.81.12:26377
    database: 3
    password: 1111  
  # 启动缓存类型
  cache:
    type: redis

集群模式配置

spring:
  application:
    name: coding-cache-redis
  redis:
    database: 3
    password: 1111
    cluster:
    #代表redis多个节点的ip与端口号,多个节点需要使用“,”隔开。
      nodes: 192.168.81.10:26375,192.168.81.11:26376,192.168.81.12:26377
      #最大重定向次数
      max-redirects: 2
  # 启动缓存类型
  cache:
    type: redis

启动缓存

在Application启动类中使用@EnableCaching注解启用缓存

@EnableCaching
@SpringBootApplication
public class CodingCacheRedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(CodingCacheRedisApplication.class, args);
    }

}

具体操作

@Service
@CacheConfig(cacheNames = "user")
public class UserService {
    @Autowired
    private UserDao userDao;

    @Cacheable
    @Transactional
    public User save(User user) {
        return userDao.save(user);
    }

    //    缓存更新
    @CachePut(key = "#user.id")
    @Transactional
    public User update(User user) {
        return userDao.save(user);
    }

    //    缓存保存
    @Cacheable(key = "#id", condition = "#id.length()>0", unless = "#id==null")
    public User findById(String id) {
        return userDao.findById(id).orElseGet(User::new);
    }

    //缓存删除
    @CacheEvict
    @Transactional
    public void delete(String id) {
        userDao.deleteById(id);
    }
}

Ehcache

EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvider 。

引入依赖

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

配置文件

application.yml

spring:
  application:
    name: coding-cache-redis
# redis配置    
  redis:
    host: localhost
    port: 6379
    password: 1111
    database: 0
# 启动缓存类型   
  cache:
    type: ehcache

在resources下添加ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>  
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
		xsi:noNamespaceSchemaLocation="ehcache.xsd">
	<diskStore path="java.io.tmpdir"/>
	<!--硬盘上缓存存储位置 -->
	<!--user.home 用户home目录 -->
	<!--user.dir 用户当前工作目录-->
	<!--java.io.tmpdir默认临时目录-->
	<defaultCache
	       eternal="false"
	       maxEntriesLocalHeap="2000"
	       timeToIdleSeconds="120"
	       timeToLiveSeconds="120"
	       overflowToDisk="false" />
	       <!-- user 缓存 -->
    <!-- name:缓存名 -->
    <!-- maxElementsInMemory:最大缓存 key 数量 -->
    <!-- timeToLiveSeconds:缓存过期时长,单位:秒 -->
    <!-- memoryStoreEvictionPolicy:缓存淘汰策略 -->
 <cache name="user"
           maxElementsInMemory="1000"
           timeToLiveSeconds="60"
           memoryStoreEvictionPolicy="LRU"/> 
	</cache>

</ehcache>

启动缓存

在Application启动类中使用@EnableCaching注解启用缓存

@EnableCaching
@SpringBootApplication
public class CodingCacheRedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(CodingCacheRedisApplication.class, args);
    }

}

具体操作

同redis


文章作者: 苏叶新城
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 苏叶新城 !
  目录