本文共 7101 字,大约阅读时间需要 23 分钟。
在Spring应用中,缓存是提升性能和减少后端负载的重要手段。Spring提供了一系列注解,简化了缓存的配置和管理。这些注解包括@Cacheable、@CachePut、@CacheEvict、@Caching和@CacheConfig等,分别用于缓存写入、更新、清除和组合操作。
@Cacheable注解用于触发缓存写入,将方法返回值存储在缓存中,以便未来重复调用时直接从缓存中获取。最简单的使用方式是注解参数指定缓存名称:
@Cacheable("books")public Book findBook(ISBN isbn) { // 该方法返回的值会被存储在名为"books"的缓存中} 一个方法可以对应多个缓存名称:
@Cacheable({"books", "isbns"})public Book findBook(ISBN isbn) { // 该方法的返回值会被存储在"books"和"isbns"两个缓存中} 缓存名称可以动态配置,如使用SpEL表达式:
@Cacheable(cacheNames="books", key="#isbn")public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) { // 缓存键由ISBN号决定} @Cacheable还支持条件判断:
@Cacheable(cacheNames="book", condition="#name.length() < 32")public Book findBook(String name) { // 只有当name长度小于32时,才会存储到缓存} @CachePut用于更新缓存,而不影响方法的执行。它的使用方式与@Cacheable类似:
@CachePut(cacheNames="book", key="#isbn")public Book updateBook(ISBN isbn, BookDescriptor descriptor) { // 该方法的返回值会被存储到缓存中} 强烈建议不要在同一方法中同时使用@Cacheable和@CachePut,以避免潜在的副作用。
@CacheEvict用于清除缓存,支持批量删除:
@CacheEvict(cacheNames="books")public void loadBooks(InputStream batch) { // 清除名为"books"的缓存}@CacheEvict(cacheNames="books", allEntries=true)public void loadBooks(InputStream batch) { // 清除所有名为"books"的缓存条目} @Caching允许在一个方法中同时进行多个缓存操作:
@Caching(evict = {@CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0")})public Book importBooks(String deposit, Date date) { // 同时清除"primary"和"secondary"缓存,并根据参数p0清除"secondary"中的条目} @CacheConfig用于在类级别配置共享的缓存设置:
@CacheConfig("books")public class BookRepositoryImpl implements BookRepository { @Cacheable public Book findBook(ISBN isbn) { // 使用"books"缓存 }} 在Spring Boot中集成Redis缓存:
pom.xml中引入Redis依赖:org.springframework.boot spring-boot-starter-data-redis
spring: redis: database: 0 url: redis://user:@127.0.0.1:6379 host: 127.0.0.1 password: port: 6379 ssl: false timeout: 5000
@Configurationpublic class CacheConfig extends CachingConfigurerSupport { @Resource private RedisConnectionFactory factory; @Bean public KeyGenerator keyGenerator() { return (o, method, objects) -> { StringBuilder sb = new StringBuilder(); sb.append(o.getClass().getName()).append("."); sb.append(method.getName()).append("."); for (Object obj : objects) { sb.append(obj.toString()); } return sb.toString(); }; } @Bean public RedisTemplate redisTemplate() { RedisTemplate template = new RedisTemplate<>(); template.setConnectionFactory(factory); return template; } @Bean @Override public CacheResolver cacheResolver() { return new SimpleCacheResolver(cacheManager()); } @Bean @Override public CacheErrorHandler errorHandler() { return new SimpleCacheErrorHandler(); } @Bean @Override public CacheManager cacheManager() { RedisCacheConfiguration cacheConfiguration = defaultCacheConfig() .disableCachingNullValues() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); return RedisCacheManager.builder(factory) .cacheDefaults(cacheConfiguration) .build(); }} @Cacheable方法@Testpublic void findUserTest() { for (int i = 0; i < 3; i++) { System.out.println("第" + i + "次"); User user = userService.findUser(); System.out.println(user); }}@Override@Cacheable(value = {"valueName", "valueName2"}, key = "'keyName1'")public User findUser() { System.out.println("执行方法..."); return new User("id1", "张三", "深圳", "1234567", 18);} @CachePut方法@Testpublic void updateUserTest() { userService.updateUser(); User user = userService.findUser(); System.out.println(user);}@Override@CachePut(value = "valueName", key = "'keyName1'")public User updateUser() { System.out.println("更新用户..."); return new User("id1", "李四", "北京", "1234567", 18);} @CacheEvict方法@Testpublic void clearUserTest() { userService.clearUser(); User user = userService.findUser(); System.out.println(user);}@Override@CacheEvict(value = "valueName", allEntries = true)public void clearUser() { System.out.println("清除缓存...");} package com.wwj.springboot.model;import java.io.Serializable;public class User implements Serializable { private String id; private String name; private String address; private String tel; private Integer age; // 以下方法省略} package com.wwj.springboot.cache;import com.wwj.springboot.model.User;import com.wwj.springboot.service.UserService;import org.junit.Test;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.cache.annotation.EnableCaching;import org.springframework.test.context.junit4.SpringRunner;import javax.annotation.Resource;@SpringBootTest@EnableCachingpublic class CacheTest { @Resource private UserService userService; @Test public void findUserTest() { for (int i = 0; i < 3; i++) { System.out.println("第" + i + "次"); User user = userService.findUser(); System.out.println(user); } } @Test public void updateUserTest() { userService.updateUser(); User user = userService.findUser(); System.out.println(user); } @Test public void clearUserTest() { userService.clearUser(); User user = userService.findUser(); System.out.println(user); }} package com.wwj.springboot.service.impl;import com.wwj.springboot.model.User;import com.wwj.springboot.service.UserService;import org.springframework.cache.annotation.CacheConfig;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;@Service@CacheConfig(cacheNames = "CacheConfigName")public class UserServiceImpl implements UserService { @Override @Cacheable(value = {"valueName", "valueName2"}, key = "'keyName1'") public User findUser() { System.out.println("执行方法..."); return new User("id1", "张三", "深圳", "1234567", 18); } @Override @CachePut(value = "valueName", key = "'keyName1'") public User updateUser() { System.out.println("更新用户..."); return new User("id1", "李四", "北京", "1234567", 18); } @Override @CacheEvict(value = "valueName", allEntries = true) public void clearUser() { System.out.println("清除缓存..."); }} 通过以上配置和示例,您可以轻松地在Spring Boot项目中实现基于注解的缓存机制。Redis作为缓存存储,能够有效提升应用的性能和响应速度。在实际项目中,建议根据具体需求合理配置缓存策略,确保既能提高性能,又能保证数据的准确性和一致性。
转载地址:http://fjqfk.baihongyu.com/