为了账号安全,请及时绑定邮箱和手机立即绑定

SpringCache学习:初学者指南

概述

本文详细介绍了SpringCache学习的相关内容,包括SpringCache的基本配置、注解使用方法以及缓存管理器的配置。文章还提供了多个实战案例,展示了如何通过SpringCache提高应用程序的性能和响应速度。

引入SpringCache

SpringCache简介

SpringCache是一个用于支持缓存的框架,通过提供一个通用的缓存抽象,使得应用程序可以在运行时动态地选择不同的缓存技术。这使得开发者能够更容易地集成和使用各种缓存方案,而无需依赖于特定的缓存实现。

SpringCache的作用和优势

SpringCache的主要作用是在应用程序中引入缓存机制,从而减少了对底层数据源的直接访问,提高了应用的响应速度和性能。其优势包括但不限于:

  1. 灵活性:SpringCache支持多种缓存实现,如Redis、Ehcache、ConcurrentHashMap等,开发者可以根据实际情况选择适合的缓存实现。
  2. 易用性:通过简单的注解,就可以启用缓存功能,无需编写复杂的缓存逻辑。
  3. 扩展性:可以在不修改业务代码的情况下更换不同的缓存技术。

SpringCache的应用场景

使用SpringCache可以提高应用程序的性能和响应速度,尤其适用于以下场景:

  1. 数据库查询:对频繁访问的数据库查询结果进行缓存,减少数据库访问次数。
  2. API调用:对于外部API调用结果进行缓存,避免频繁调用API产生的延迟。
  3. 静态资源:对于静态资源的访问,如静态图片、静态文件等,可以进行缓存以提高访问速度。
SpringCache的基本配置

添加SpringCache依赖

要使用SpringCache,首先需要在项目中添加SpringCache相关的依赖。对于基于Maven的项目,可以在pom.xml文件中添加如下依赖:

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

对于基于Gradle的项目,可以在build.gradle文件中添加如下依赖:

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-cache:2.6.3'
}

配置SpringCache的基本属性

在SpringBoot项目中,可以通过application.propertiesapplication.yml文件配置SpringCache的相关属性。例如,启用缓存功能并指定默认的缓存管理器:

spring.cache.type=simple # 指定缓存类型,如simple、couchbase等
spring.cache.cache-names=exampleCache # 设置缓存名称

此外,还可以配置具体的缓存实现的属性,比如使用Ehcache时:

spring.cache.ehcache.config=classpath:ehcache.xml # 指定Ehcache的配置文件

使用注解启用缓存

SpringCache提供了几个重要的注解来启用缓存功能:

  • @EnableCaching:启用SpringCache功能,必须添加到SpringBoot启动类中。
  • @Cacheable:标记的方法结果将被缓存。
  • @CachePut:标记的方法将被缓存,但不会影响方法的执行。
  • @CacheEvict:标记的方法将清除缓存中的数据。

下面是一个简单的示例,展示如何在SpringBoot启动类中启用缓存:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
缓存的使用

@Cacheable注解的使用

@Cacheable注解用于标记方法,当方法被调用时,它的返回值将被缓存。当再次调用该方法并使用相同的参数时,将直接从缓存中获取结果,而不是执行方法。

示例代码如下:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        // 模拟数据库查询
        return new User(id, "User " + id);
    }
}

@CachePut注解的使用

@CachePut注解用于标记方法,该方法的执行结果将被缓存,但不会影响方法的执行流程。例如,当某个方法的执行结果需要更新缓存时,可以使用@CachePut

示例代码如下:

import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @CachePut(value = "users", key = "#id")
    public User updateUser(Long id, User user) {
        // 模拟数据库更新操作
        return new User(id, "Updated User " + id);
    }
}

@CacheEvict注解的使用

@CacheEvict注解用于标记方法,当该方法执行时,将会清除指定缓存中的数据。例如,当删除用户时,可以使用@CacheEvict注解清除缓存中的用户信息。

示例代码如下:

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @CacheEvict(value = "users", key = "#id")
    public void deleteUser(Long id) {
        // 模拟数据库删除操作
    }
}
缓存管理器和缓存解析器

自定义缓存管理器

缓存管理器是SpringCache中的核心组件,负责管理缓存实例。可以通过实现CacheManager接口来自定义缓存管理器。

示例代码如下:

import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        ConcurrentMapCacheFactoryBean factory = new ConcurrentMapCacheFactoryBean();
        factory.setCacheNames(Arrays.asList("users", "orders"));
        return factory.getObject();
    }
}

使用SpringCache提供的缓存解析器

SpringCache提供了多种缓存解析器,如CachingConfigurerSupport,可以通过它来配置缓存管理器。

示例代码如下:

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.config.CacheConfiguration;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {

    @Bean
    public SimpleCacheManager cacheManager() {
        return new SimpleCacheManager();
    }
}

缓存管理器和缓存解析器的配置

配置缓存管理器和缓存解析器通常是在SpringBoot的配置类中进行。例如,可以在CacheConfig类中配置缓存管理器。

示例代码如下:

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean;

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        ConcurrentMapCacheFactoryBean factory = new ConcurrentMapCacheFactoryBean();
        factory.setCacheNames(Arrays.asList("users", "orders"));
        return factory.getObject();
    }
}
缓存的自定义

自定义缓存键

默认情况下,@Cacheable@CachePut@CacheEvict注解使用方法参数作为缓存键。可以通过key属性自定义缓存键。

示例代码如下:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        // 模拟数据库查询
        return new User(id, "User " + id);
    }
}

自定义缓存失效时间

可以通过CacheConfig中的TimeToLive属性来自定义缓存的失效时间。

示例代码如下:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Cacheable(value = "users", key = "#id", timeToLive = 60000) // 缓存失效时间为60秒
    public User getUserById(Long id) {
        // 模拟数据库查询
        return new User(id, "User " + id);
    }
}

处理缓存穿透、缓存击穿和缓存雪崩

缓存穿透、缓存击穿和缓存雪崩是常见的缓存问题,可以通过以下策略进行处理:

  • 缓存穿透:可以使用布隆过滤器或Redis的setNx命令来防止未命中缓存的情况。
  • 缓存击穿:可以使用互斥锁或分布式锁来防止缓存失效时的大量请求。
  • 缓存雪崩:可以使用缓存预热、增加缓存的过期时间、设置多个缓存层等策略。

示例代码如下:

import org.springframework.cache.annotation.Cacheable;
import redis.clients.jedis.Jedis;

@Service
public class UserService {

    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        Jedis jedis = new Jedis();
        String userJson = jedis.get("user_" + id);
        if (userJson != null) {
            return User.fromJSON(userJson);
        } else {
            // 模拟数据库查询
            User user = new User(id, "User " + id);
            jedis.set("user_" + id, user.toJSON());
            return user;
        }
    }
}
实践案例

实战:简单的缓存优化案例

本案例演示如何对一个频繁访问的数据库查询进行缓存优化。

  1. 定义Entity
public class User {
    private Long id;
    private String name;

    public User() {}

    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    // Getters and Setters
}
  1. 定义Service
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        // 模拟数据库查询
        return new User(id, "User " + id);
    }
}
  1. 定义Controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    UserService userService;

    @GetMapping("/user/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }
}

实战:缓存与数据库的结合使用案例

本案例演示如何在缓存失效时回填缓存数据。

  1. 定义Service
import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @CachePut(value = "users", key = "#id")
    public User updateUser(Long id, User user) {
        // 模拟数据库更新操作
        return new User(id, "Updated User " + id);
    }
}
  1. 定义Controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    UserService userService;

    @PutMapping("/user/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        return userService.updateUser(id, user);
    }
}

实战:自定义缓存策略的实现

本案例演示如何自定义缓存策略,例如使用布隆过滤器防止缓存穿透。

  1. 定义布隆过滤器
import org.apache.commons.lang3.RandomUtils;

public class BloomFilter {
    private long[] bits;

    public BloomFilter(int size) {
        bits = new long[size / 64];
    }

    public void add(long key) {
        int index = (int) (key % bits.length);
        bits[index] |= 1L << (key & 0x3F);
    }

    public boolean contains(long key) {
        int index = (int) (key % bits.length);
        return (bits[index] & (1L << (key & 0x3F))) != 0;
    }

    public static void main(String[] args) {
        BloomFilter filter = new BloomFilter(1024);
        for (int i = 0; i < 100; i++) {
            filter.add(RandomUtils.nextLong());
        }
        System.out.println(filter.contains(RandomUtils.nextLong()));
    }
}
  1. 定义Service
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        BloomFilter filter = new BloomFilter(1024);
        if (filter.contains(id)) {
            // 模拟数据库查询
            return new User(id, "User " + id);
        } else {
            // 缓存穿透处理
            return null;
        }
    }
}
  1. 定义Controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    UserService userService;

    @GetMapping("/user/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }
}

通过这些示例代码,我们可以更好地理解和应用SpringCache的各个特性,从而提高应用程序的性能和响应速度。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消