您的位置:

Spring Boot缓存详解

随着应用程序越来越复杂,解决性能问题变得越来越重要。缓存是提高应用程序性能的重要方式之一。Spring Boot框架集成了多种缓存技术,使得开发人员可以快速、方便地使用缓存。本文将从多个方面详细介绍Spring Boot缓存。

一、@Cacheable注解

Spring Boot缓存最常用的方式是使用@Cacheable注解。使用该注解可以将方法返回值缓存到内存或磁盘中,下次请求时如果参数和缓存中的一致,则直接返回缓存结果。为了使用@Cacheable注解,我们需要做以下三件事情:

1、在pom文件中引入Spring Boot的缓存依赖。例如,如果我们想使用Ehcache缓存,那么可以使用以下依赖:

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

2、在应用程序主类上添加@EnableCaching注解。例如:

@SpringBootApplication
@EnableCaching
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

3、在需要缓存的方法上添加@Cacheable注解即可。例如:

@Cacheable(value = "myCache", key = "#id")
public User getUserById(Long id) {
    // 从数据库获取数据
    User user = userRepository.findById(id);
    return user;
}

在上面的代码中,我们使用了value参数指定了缓存的名称,key参数指定了缓存的键值。

二、缓存注解参数详解

除了@Cacheable注解外,Spring Boot还提供了多个缓存注解,例如@CachePut、@CacheEvict、@Caching等。以下是这些缓存注解的详细说明:

@Cacheable

该注解用于在方法调用之前,检查缓存中是否存在请求的数据。如果缓存存在数据,则将缓存数据返回;否则会执行方法,并将执行结果存入缓存中。例如:

@Cacheable(value = "myCache", key = "#id")
public User getUserById(Long id) {
    // 从数据库获取数据
    User user = userRepository.findById(id);
    return user;
}

在上面的代码中,我们使用了value参数指定了缓存的名称,key参数指定了缓存的键值。

@CachePut

该注解用于在方法执行成功时,将返回值存入缓存中。例如:

@CachePut(value = "myCache", key = "#user.id")
public User updateUser(User user) {
    // 更新数据库中的数据
    User updatedUser = userRepository.save(user);
    return updatedUser;
}

在上面的代码中,我们使用了value参数指定了缓存的名称,key参数指定了缓存的键值。

@CacheEvict

该注解用于清除指定的缓存数据。例如:

@CacheEvict(value = "myCache", key = "#id")
public void deleteUser(Long id) {
    // 从数据库删除数据
    userRepository.deleteById(id);
}

在上面的代码中,我们使用了value参数指定了缓存的名称,key参数指定了缓存的键值。

@Caching

该注解可以组合多种缓存注解,例如:

@Caching(
    cacheable = @Cacheable(value = "myCache", key = "#username"),
    put = @CachePut(value = "myCache", key = "#result.id"),
    evict = @CacheEvict(value = "myCache", key = "#id")
)
public User getUserByUsernameAndId(String username, Long id) {
    // 从数据库获取数据
    User user = userRepository.findByUsernameAndId(username, id);
    return user;
}

三、缓存管理器

Spring Boot提供了多个缓存管理器,例如Ehcache、Redis等。以下是缓存管理器的详细说明:

Ehcache

使用Ehcache作为Spring Boot的缓存管理器,我们需要在pom文件中引入Ehcache的依赖,例如:

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

然后在应用程序配置文件application.yml中,我们需要配置Ehcache。以下是一个简单的Ehcache配置:

spring:
  cache:
    type: ehcache

ehcache:
  config: classpath:ehcache.xml

在上面的配置中,我们使用了type参数指定了使用Ehcache作为缓存管理器,config参数指定了Ehcache的配置文件。

Redis

使用Redis作为Spring Boot的缓存管理器,我们需要在pom文件中引入Spring Boot的Redis依赖,例如:

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

然后,在应用程序配置文件application.yml中,我们需要配置Redis。以下是一个简单的Redis配置:

spring:
  cache:
    type: redis

redis:
  host: localhost
  port: 6379
  password:
  timeout: 3000

在上面的配置中,我们使用了type参数指定了使用Redis作为缓存管理器,Redis的连接信息在redis节点中进行配置。

四、缓存管理器与多个缓存

在Spring Boot中,我们可以同时使用多个缓存管理器,并为不同的缓存使用不同的缓存管理器。以下是一个基于Ehcache和Redis缓存管理器的示例:

@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public CacheManager ehcacheManager() {
        EhCacheCacheManager cacheManager = new EhCacheCacheManager(getEhCacheFactory().getObject());
        return cacheManager;
    }

    @Bean
    public CacheManager redisManager() {
        RedisCacheManager cacheManager = new RedisCacheManager(getRedisTemplate());
        cacheManager.setDefaultExpiration(60);
        return cacheManager;
    }

    @Bean
    public EhCacheManagerFactoryBean getEhCacheFactory() {
        EhCacheManagerFactoryBean factoryBean = new EhCacheManagerFactoryBean();
        factoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
        factoryBean.setShared(true);
        return factoryBean;
    }

    @Bean
    public RedisTemplate getRedisTemplate() {
        RedisTemplate
    redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(getRedisConnectionFactory());
        redisTemplate.setDefaultSerializer(new StringRedisSerializer());
        return redisTemplate;
    }

    @Bean
    public RedisConnectionFactory getRedisConnectionFactory() {
        LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory();
        connectionFactory.setHostName("localhost");
        connectionFactory.setPort(6379);
        return connectionFactory;
    }
}

   
  

在上面的代码中,我们使用@Configuration注解和@Bean注解定义了两个缓存管理器:ehcacheManager和redisManager。在ehcacheManager中,我们使用了EhCacheCacheManager类来定义Ehcache管理器;在redisManager中,我们使用了RedisCacheManager类来定义Redis管理器。在getEhCacheFactory和getRedisTemplate方法中,我们使用了EhCacheManagerFactoryBean和RedisTemplate类来设置Ehcache和Redis的配置信息。

当我们在使用@Cacheable注解的时候,我们可以使用value参数指定缓存的名称,也可以使用cacheManager参数指定使用的缓存管理器。例如:

@Cacheable(value = "myCache", cacheManager = "ehcacheManager", key = "#id")
public User getUserById(Long id) {
    // 从数据库获取数据
    User user = userRepository.findById(id);
    return user;
}

五、缓存清理和失效

使用缓存时,我们需要注意缓存的清理和失效。以下是缓存清理和失效的说明:

手动清理缓存

我们可以使用@CacheEvict注解清理缓存,也可以使用CacheManager类的clearCache方法清理缓存。例如:

@Autowired
private CacheManager cacheManager;

// 清理所有缓存
cacheManager.getCacheNames().forEach(cacheName -> cacheManager.getCache(cacheName).clear());

// 清理指定缓存
cacheManager.getCache("myCache").clear();

// 使用@CacheEvict清理缓存
@CacheEvict(value = "myCache", allEntries = true)
public void clearCache() {
    ...
}

在上面的代码中,我们首先使用cacheManager.getCacheNames()方法获取所有缓存的名称,然后在循环中使用cacheManager.getCache方法获取每个缓存对象,最后使用clear方法清理缓存。

失效时间

我们可以使用@Cacheable注解的timeToLive参数或CacheManager类的setDefaultExpiration方法来设置缓存失效时间。例如:

@Cacheable(value = "myCache", key = "#id", timeToLive = 3600)
public User getUserById(Long id) {
    // 从数据库获取数据
    User user = userRepository.findById(id);
    return user;
}

@Autowired
private CacheManager cacheManager;

// 设置所有缓存的失效时间
cacheManager.setDefaultExpiration(60);

// 设置指定缓存的失效时间
cacheManager.getCache("myCache").getNativeCache().getCacheConfiguration().setTimeToLiveSeconds(3600);

在上面的代码中,我们使用了timeToLive参数和setDefaultExpiration方法设置了缓存的失效时间。

条件失效

我们可以使用@CachePut注解的condition参数来定义缓存的条件失效。例如,我们可以在更新用户信息的方法中,只有在用户数据发生变化时才更新缓存:

@CachePut(value = "myCache", key = "#user.id", condition = "#user.changed == true")
public User updateUser(User user) {
    // 更新数据库中的数据
    User updatedUser = userRepository.save(user);
    // 标记变化
    updatedUser.setChanged(true);
    return updatedUser;
}

六、缓存监控

Spring Boot提供了多种工具来监控缓存,例如Actuator、Micrometer等。以下是缓存监控的详细说明:

Actuator

Spring Boot Actuator是Spring Boot的生产环境管理工具,提供了对应用程序的监控和管理功能。我们可以使用Actuator来监控应用程序中缓存的使用情况。例如,在浏览器中访问URL http://localhost:8080/actuator/caches/可以查看当前应用程序中所有缓存的使用情况:

{
  "cacheManagers": {
    "cacheManager": {
      "caches": {
        "myCache": {
          "target": {
            "class": "org.springframework.data.redis.cache.RedisCache",
            "name": "myCache",
            "cache": {
              "cacheName": "myCache",
              "nativeCache": {
                "name": "myCache",
                "cacheLoader": null,
                "cacheWriter": null,
                "evictionAdvisor": null,
                "initializer": null,
                "loaderWriterMutex": {},
                "stats": {
                  "cacheHits": 1,