【springboot】缓存之@Cacheable、@CachePut、@CacheEvict的用法

news2024/9/27 21:18:31

目录

        • 一、注解参数说明
          • 1.1 属性说明
            • 1.1.1 value/cacheNames 属性
            • 1.1.2 key属性
            • 1.1.3 keyGenerator属性
            • 1.1.4 cacheManager属性
            • 1.1.5 cacheResolver属性
            • 1.1.6 condition属性
            • 1.1.7 unless 属性
            • 1.1.8 sync 属性
          • 1.2 @Cacheable注解
          • 1.3 @CachePut注解
          • 1.4 @CacheEvict注解
            • 1.4.1 allEntries属性
            • 1.4.2 beforeInvocation属性
        • 二、代码示例
          • 2.1 基本框架搭建
          • 2.2 value属性与cacheNames属性
            • 2.2.1 单个缓存代码示例
            • 2.2.2 单个缓存效果截图
            • 2.2.3 多个缓存代码示例
            • 2.2.4 多个缓存效果截图
          • 2.3 key属性
            • 2.3.1 方法没有参数示例
            • 2.3.2 方法没有参数截图
            • 2.3.3 方法有一个参数示例
            • 2.3.4 方法有一个参数截图
            • 2.3.5 方法有多个参数示例
            • 2.3.6 方法有多个参数截图
            • 2.3.7 指定key(从参数中指定)
            • 2.3.8 指定key截图
          • 2.4 keyGenerator属性
            • 2.4.1 自定义key生成器代码示例
            • 2.4.2 自定义key生成器截图
          • 2.5 cacheResolver属性
            • 2.5.1 自定义cacheResolver缓存解析器代码示例
            • 2.5.2 自定义cacheResolver缓存解析器截图
          • 2.6 condition属性
            • 2.6.1 指定条件进行缓存代码示例
            • 2.6.2 指定条件进行缓存截图
          • 2.7 unless属性
            • 2.7.1 指定条件不进行缓存代码示例
            • 2.7.2 结果为null的缓存截图
          • 2.8 allEntries属性
            • 2.8.1 清除全部缓存代码示例
            • 2.8.2 先查2次缓存起来,然后删除1条,清除所有截图

一、注解参数说明

1.1 属性说明
1.1.1 value/cacheNames 属性
  • 1.这两个属性代表的意义相同
  • 2.用来指定缓存组件的名称,将方法的返回结果存进缓存的名称
  • 3.定义为数组时,可以存到多个缓存key中
1.1.2 key属性
  • 1.指定缓存数据的key
1.#root.method.name:当前被调用的方法名
2.#root.methodName:当前被调用的方法
3.#root.target:当前被调用的目标对象
4.#root.targetClass:当前被调用的目标对象类
5.#root.args[0]:当前被调用的方法的参数列表
6.#root.caches[0].name:当前方法调用使用的缓存列表(@Cacheable(value={"cache1","cache2"}))
7.#id、#p0、#a0:方法参数的名字,可以#参数名,也可以使用 #p0或#a0 的形式,0代表参数的索引
8.#result:方法执行后的返回值(仅当方法执行之后的判断有效,如’unless’、@cacheput和@cacheevict的表达式beforeInvocation=false)
  • 2.redis作为缓存时,redis中的key为value::key
  • 3.方法没有参数时,key=new SimpleKey()
  • 4.方法有一个参数时,key=参数的值
  • 5.方法有多个参数时,key=new SimpleKey(params);
1.1.3 keyGenerator属性
  • 1.key 的生成器
  • 2.可以自定义key的生成器的组件id
  • 3.key与keyGenerator二选一使用
  • 4.可以自定义配置类,将 keyGenerator 注册到 IOC 容器
1.1.4 cacheManager属性
  • 1.用来指定缓存管理器
  • 2.对不同的缓存技术,实现不同的cacheManager,spring定义了一些 cacheManger的实现
  • 3.SimpleCacheManager:使用简单的Collection来存储缓存(默认)
  • 4.ConcurrentMapCacheManager:使用ConcurrentMap作为缓存技术
  • 5.NoOpCacheManager:测试用
  • 6.EhCacheCacheManager:使用EhCache作为缓存技术,hibernate经常用
  • 7.GuavaCacheManager:使用google的guava的GuavaCache作为缓存技术
  • 8.HazelcastCacheManager:使用Hazelcast作为缓存技术
  • 9.JCacheCacheManager:使用JCache标准的实现作为缓存技术,如Apache Commons JCS
  • 10.RedisCacheManager:使用Redis作为缓存技术
1.1.5 cacheResolver属性
  • 1.指定自定义的缓存管理器
  • 2.cacheManager缓存管理器与cacheResolver自定义解析器二选一使用
1.1.6 condition属性
  • 1.符合指定的条件才可以缓存
  • 2.可以通过 SpEL 表达式进行设置
1.1.7 unless 属性
  • 1.unless的条件为 true 时,方法的返回值不会被缓存
  • 2.可以在获取到结果后进行判断
1.1.8 sync 属性
  • 1.是否使用同步模式
  • 2.异步模式下 unless 属性不可用
  • 3.sync=true:同步模式,若多个线程尝试为同一个key缓存值,当一个线程缓存成功后,其它线程便直接拿缓存后的数据,不会再去查库缓存,能解决缓存击穿问题;一个线程去新建,新建成功后其它线程才能拿
  • 4.默认是false
1.2 @Cacheable注解
  • 1.每次执行方法前都会检查cache中是否存在相同key的缓存,如果存在就不再执行该方法,直接从缓存中获取结果进行返回,如果不存在则会执行该方法并将结果存入指定key的缓存中
1.3 @CachePut注解
  • 1.在执行方法前不会去检查缓存中是否存在key的缓存,每次都会执行该方法,并将执行结果存入指定key的缓存中
  • 2.使用在保存,更新方法中
  • 3.标注在类上和方法
1.4 @CacheEvict注解
  • 1.标注在需要清除缓存的方法或类
  • 2.标记在类上时表示其中所有方法的执行都会触发缓存的清除操作
  • 3.@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation
1.4.1 allEntries属性
  • 1.allEntries为true时,清除value属性值中的所有缓存,更有效率
  • 2.默认为false,可以指定清除value属性值下具体某个key的缓存
1.4.2 beforeInvocation属性
  • 1.默认是false,即在方法执行成功后触发删除缓存的操作
  • 2.如果方法抛出异常未能成功返回,不会触发删除缓存的操作
  • 3.当改为true时,方法执行之前会清除指定的缓存,这样不论方法执行成功还是失败都会清除缓存

二、代码示例

2.1 基本框架搭建
  • 1.导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-learning</artifactId>
        <groupId>com.learning</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springboot-cache</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- springboot web启动类-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!-- mybatis-plus依赖包 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <!-- mysql依赖包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- cache依赖 -->
        <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>
    </dependencies>
</project>
  • 2.application.yaml配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root
  cache:
    type: redis
  redis:
    host: 127.0.0.1
    port: 6379
mybatis-plus:
  global-config:
    db-config:
      id-type: auto
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • 3.接口类
package com.learning.cache.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @Description 接口类
 */
@RestController
@RequestMapping("student")
public class StudentController {

    @Autowired
    private StudentService studentService;

    @ResponseBody
    @GetMapping("/list")
    public List<Student> getList(){
        return studentService.list();
    }

    @ResponseBody
    @GetMapping("/{id}")
    public Student getById(@PathVariable String id){
        return studentService.getById(id);
    }

    @ResponseBody
    @GetMapping("/page")
    public Page<Student> getPage(@RequestParam int size, @RequestParam int current){
        return studentService.page(size, current);
    }

    @ResponseBody
    @PostMapping("/save")
    public Student save(@RequestBody Student student){
        return studentService.save(student);
    }

    @DeleteMapping("/{id}")
    public boolean delete(@PathVariable String id){
        return studentService.delete(id);
    }
}


  • 4.service实现类
package com.learning.cache.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;

    @Cacheable(value={"com:learning:cache:list"})
    @Override
    public List<Student> list() {
        return studentDao.selectList(null);
    }

    @Cacheable(value="com:learning:cache:one")
    @Override
    public Student getById(String id) {
        return studentDao.selectById(id);
    }

    @Cacheable(value={"com:learning:cache:more"})
    @Override
    public Page<Student> page(int size, int current) {
        Page<Student> page = new Page<>();
        page.setCurrent(current);
        page.setSize(size);
        return studentDao.selectPage(page, null);
    }

    @Override
    public Student save(Student student) {
        int result = studentDao.insert(student);
        if(result > 0){
            return student;
        }
        return null;
    }

    @CacheEvict(value="com:learning:cache:one", allEntries = true)
    @Override
    public boolean delete(String id) {
        int result = studentDao.deleteById(id);
        if(result > 0){
            return true;
        }
        return false;
    }
}

  • 5.service接口类
package com.learning.cache.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.entity.Student;

import java.util.List;

public interface StudentService {
    List<Student> list();
    Student getById(String id);
    Page<Student> page(int size, int current);
    Student save(Student student);
    boolean delete(String id);
}

  • 6.持久层类
package com.learning.cache.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.learning.cache.entity.Student;
import org.apache.ibatis.annotations.Mapper;

/**
 * @Description 学生持久层类
 */
@Mapper
public interface StudentDao extends BaseMapper<Student> {
}
  • 7.启动类
package com.learning.cache;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
/**
 * @Description 启动类
 */
@SpringBootApplication
// 开启启用缓存注解
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • 8.配置类
package com.learning.cache.config;

import com.learning.cache.resolver.CustomCacheResolver;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;

/**
 * @Description 自定义Key生成器
 */
@Configuration
public class CacheResolverConfig {
    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .computePrefixWith(cacheName -> cacheName.concat(":"));

        return RedisCacheManager.builder(redisConnectionFactory)
                .cacheDefaults(cacheConfiguration)
                .build();

    }

    @Bean("customCacheResolver")
    public CacheResolver customCacheResolver(RedisConnectionFactory redisConnectionFactory) {
        return new CustomCacheResolver(redisCacheManager(redisConnectionFactory));
    }
}
package com.learning.cache.config;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.UUID;

/**
 * @Description 自定义Key生成器
 */
@Configuration
public class KeyGeneratorConfig {
    @Bean("customKeyGenerator")
    public KeyGenerator keyGenerator(){
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                return method.getName() + Arrays.asList(objects).toString() + UUID.randomUUID();
            }
        };
    }
}

package com.learning.cache.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description 分页配置类
 */
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

package com.learning.cache.resolver;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.*;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import java.lang.reflect.Method;
import java.util.Collection;

/**
 * @Description 自定义缓存解析器
 */
@Slf4j
public class CustomCacheResolver extends SimpleCacheResolver {
    public CustomCacheResolver(CacheManager cacheManager) {
        super(cacheManager);
    }

    @Override
    public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
        // 拿到缓存
        Collection<? extends Cache> caches = super.resolveCaches(context);
        Object target = context.getTarget();
        BasicOperation operation = context.getOperation();
        Method method = context.getMethod();
        Object[] args = context.getArgs();
        ParameterNameDiscoverer paramNameDiscoverer = new DefaultParameterNameDiscoverer();
        EvaluationContext evaluationContext = new MethodBasedEvaluationContext(context.getOperation(), context.getMethod(), context.getArgs(), paramNameDiscoverer);
        Expression expression = (new SpelExpressionParser()).parseExpression(((CacheableOperation) context.getOperation()).getKey());
        // 获取所有的缓存的名字
        context.getOperation().getCacheNames().forEach(cacheName -> {
            log.info("缓存的name:{}", cacheName);
            String key = cacheName + ':' + expression.getValue(evaluationContext, String.class);
            log.info("缓存的key全路径:{}", key);
        });
        // 返回缓存
        return caches;
    }
}

2.2 value属性与cacheNames属性
2.2.1 单个缓存代码示例
package com.learning.cache.service.impl;

import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentDao studentDao;
	// com:learning:cache会作为redis的key的一部分
    @Cacheable(value="com:learning:cache:list")
    @Override
    public List<Student> list() {
        return studentDao.selectList(null);
    }
}
2.2.2 单个缓存效果截图

在这里插入图片描述

2.2.3 多个缓存代码示例
package com.learning.cache.service.impl;

import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;
	// 多个值,会将方法的返回结果存入到不同的缓存key中
    @Cacheable(value={"com:learning:cache:list","cn:learning:cache:list"})
    @Override
    public List<Student> list() {
        return studentDao.selectList(null);
    }
}

2.2.4 多个缓存效果截图

在这里插入图片描述

2.3 key属性
2.3.1 方法没有参数示例
package com.learning.cache.service.impl;

import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;

    @Cacheable(value={"com:learning:cache:list"})
    @Override
    public List<Student> list() {
        return studentDao.selectList(null);
    }
}
2.3.2 方法没有参数截图

在这里插入图片描述

2.3.3 方法有一个参数示例
package com.learning.cache.service.impl;

import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;

    // String id 一个参数的key情况
    @Cacheable(value={"com:learning:cache:one"})
    @Override
    public Student getById(String id) {
        return studentDao.selectById(id);
    }
}

2.3.4 方法有一个参数截图

在这里插入图片描述

2.3.5 方法有多个参数示例
package com.learning.cache.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;

    @Cacheable(value={"com:learning:cache:more"})
    @Override
    public Page<Student> page(int size, int current) {
        Page<Student> page = new Page<>();
        page.setCurrent(current);
        page.setSize(size);
        return studentDao.selectPage(page, null);
    }
}

2.3.6 方法有多个参数截图

在这里插入图片描述

2.3.7 指定key(从参数中指定)
package com.learning.cache.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;

    @Cacheable(value="com:learning:cache:one", key="#id")
    @Override
    public Student getById(String id) {
        return studentDao.selectById(id);
    }
}

2.3.8 指定key截图

在这里插入图片描述

2.4 keyGenerator属性
2.4.1 自定义key生成器代码示例
package com.learning.cache.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;

    @Cacheable(value="com:learning:cache:one", keyGenerator="customKeyGenerator")
    @Override
    public Student getById(String id) {
        return studentDao.selectById(id);
    }  
}

package com.learning.cache.config;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;
import java.sql.Statement;
import java.util.Arrays;
import java.util.UUID;

/**
 * @Description 自定义Key生成器
 */
@Configuration
public class KeyGeneratorConfig {
    @Bean("customKeyGenerator")
    public KeyGenerator keyGenerator(){
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                return method.getName() + Arrays.asList(objects).toString() + UUID.randomUUID();
            }
        };
    }
}

2.4.2 自定义key生成器截图

在这里插入图片描述

2.5 cacheResolver属性
2.5.1 自定义cacheResolver缓存解析器代码示例
package com.learning.cache.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;

    @Cacheable(value="com:learning:cache:one",key="#id", cacheResolver="customCacheResolver")
    @Override
    public Student getById(String id) {
        return studentDao.selectById(id);
    }
}
package com.learning.cache.resolver;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.*;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import java.lang.reflect.Method;
import java.util.Collection;

/**
 * @Description 自定义缓存解析器
 */
@Slf4j
public class CustomCacheResolver extends SimpleCacheResolver {
    public CustomCacheResolver(CacheManager cacheManager) {
        super(cacheManager);
    }

    @Override
    public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
        // 拿到缓存
        Collection<? extends Cache> caches = super.resolveCaches(context);
        Object target = context.getTarget();
        BasicOperation operation = context.getOperation();
        Method method = context.getMethod();
        Object[] args = context.getArgs();
        ParameterNameDiscoverer paramNameDiscoverer = new DefaultParameterNameDiscoverer();
        EvaluationContext evaluationContext = new MethodBasedEvaluationContext(context.getOperation(), context.getMethod(), context.getArgs(), paramNameDiscoverer);
        Expression expression = (new SpelExpressionParser()).parseExpression(((CacheableOperation) context.getOperation()).getKey());
        // 获取所有的缓存的名字
        context.getOperation().getCacheNames().forEach(cacheName -> {
            log.info("缓存的name:{}", cacheName);
            String key = cacheName + ':' + expression.getValue(evaluationContext, String.class);
            log.info("缓存的key全路径:{}", key);
        });
        // 返回缓存
        return caches;
    }
}

2.5.2 自定义cacheResolver缓存解析器截图

在这里插入图片描述

在这里插入图片描述

2.6 condition属性
2.6.1 指定条件进行缓存代码示例
package com.learning.cache.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;

	// 指定id为1的可以缓存
    @Cacheable(value="com:learning:cache:one", condition = "#id eq '1'")
    @Override
    public Student getById(String id) {
        return studentDao.selectById(id);
    }
}
2.6.2 指定条件进行缓存截图

在这里插入图片描述
在这里插入图片描述

2.7 unless属性
2.7.1 指定条件不进行缓存代码示例
package com.learning.cache.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;
	// 对查询结果为null的不做缓存,去掉的话会缓存空值
    @Cacheable(value="com:learning:cache:one", unless = "#result == null")
    @Override
    public Student getById(String id) {
        return studentDao.selectById(id);
    }
}

2.7.2 结果为null的缓存截图

在这里插入图片描述

2.8 allEntries属性
2.8.1 清除全部缓存代码示例
package com.learning.cache.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Description 学生服务实现类
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;
    
    @Cacheable(value="com:learning:cache:one")
    @Override
    public Student getById(String id) {
        return studentDao.selectById(id);
    }

    @CacheEvict(value="com:learning:cache:one", allEntries = true)
    @Override
    public boolean delete(String id) {
        int result = studentDao.deleteById(id);
        if(result > 0){
            return true;
        }
        return false;
    }
}

2.8.2 先查2次缓存起来,然后删除1条,清除所有截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/438931.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

低代码产品如何分类,大部分人都没有搞清楚

最近许多技术峰会都出现了低代码这个名词&#xff0c;可以说&#xff0c;低代码是中台之后&#xff0c;又一个热门话题和名词了。 一、什么是低代码平台&#xff1f; 低代码平台是无需编码或通过少量代码就可以快速生成应用程序的开发平台。也是一款图形化、拖拉拽方式快速实…

hadoop伪分布式安装

文章目录 1. 将安装包hadoop-3.1.3.tar.gz上次至linux中2. 进行解压操作3. 修改目录名称4. 配置环境变量5. 修改自定义配置文件5.1 hadoop-env.sh5.2 core-site.xml5.3 hdfs-site.xml5.4 workers 6. 格式化集群7. 免密登录8. 启动hdfs9. 关闭hdfs 1. 将安装包hadoop-3.1.3.tar.…

群晖NAS与阿里云盘同步的方法

同步方法&#xff1a;通过在 docker 中安装 aliyundrive-webdav 实现与阿里云盘同步。 下载和安装 aliyundrive-webdav 在 docker 的注册表中搜素 aliyun&#xff0c;选择点赞比较多的 messense/aliyundrive-webdav&#xff1a; 下载后安装。建议在配置和启动之前&#xff…

Docker 的安装和镜像容器的基本操作

文章目录 一、Docker 概述1、Docker的概念2、容器的优点3、容器与虚拟机的区别4、容器在内核中支持2种重要技术5、Docker核心概念 二、Docker的安装1、docker的安装步骤2、实例操作&#xff1a;安装docker 三、Docker 镜像操作1、搜索镜像2、获取镜像3、镜像加速下载4、查看镜像…

基础工业工程(易树平、郭伏)——第三草 工作研究

第三草 工作研究 第一节 工作研究概述 一、工作研究的对象 工作研究的对象是作业系统&#xff0c;这是一个由多个相互关联的因素所组成的有机整体&#xff0c;旨在实现预定的功能和目标。作业系统的目标表现为输出一定的“产品”或“服务”&#xff0c;主要由材料、设备、能…

超级简洁、彻底组件化的轻量级Android Kotlin Jetpack MVVM组件化框架

结构 特点&#xff1a; 彻底组件化&#xff0c;且更简洁&#xff0c;Module具有独立的Application、AndroidMinifast、资源文件等&#xff1b;Application和Library的切换更加快捷&#xff1b;超级简洁、且多功能的网络层封装&#xff0c;自带2级缓存&#xff0c;App端内嵌了日…

盛元广通高校实验室安全智能管理平台

实验室安全问题一直以来都是高校管理的重点&#xff0c;依据《高等学校实验室安全规范》相关要求&#xff0c;应教育相关部门以及应急管理部门的相关规定&#xff0c;关于安全工作的系列重要指示和部署&#xff0c;必须按照危险源管控分级管理体系对实验室进行分级分类管理&…

ebay、速卖通、ozon销量下滑怎么办?怎样可以提高转化率

单量不好&#xff0c;就开始焦虑&#xff0c;而真正需要了解为什么会出现销量下滑的原因&#xff0c;从不断更新自己的知识&#xff0c;提高自己的技能&#xff0c;如何提高自己的技能呢&#xff1f; 把所学到的知识学以致用&#xff0c;listing的评分&#xff0c;退货率&…

ESP32学习四-自定义分区表

1、简介 ESP32-WROOM-32集成了4MB SPI FLASH。对应的&#xff0c;也会对这4MB FLAHS进行分区处理。在编译esp32程序时&#xff0c;通过make menuconfig -> Partition Table可以设置三种分区。 工厂程序&#xff08;无OTA分区&#xff09; 工厂程序&#xff08;双OTA分…

自旋锁/读者写者问题

自旋锁 自旋锁的概念和理解 锁在处理需要申请加锁的线程的时候&#xff0c;一般有两种处理方法&#xff1a;一种是挂起等待&#xff0c;另外一种是自旋。自旋即轮询。 挂起等待&#xff1a; 当一个线程成功申请锁&#xff0c;并进入临界区后&#xff0c;其它线程在申请的时候…

【经验分享】硬件工程师需要知道的DFM可制造性设计

最近&#xff0c;有硬件工程师朋友找我讨论DFM&#xff0c;也就是可制造性设计。Design for Manufacturability。 什么是可制造性设计&#xff0c;看一张图很容易明白&#xff1a; 过大的PCB&#xff0c;无法上产线批量生产&#xff0c;极大的PCB面积浪费&#xff0c;自然是失…

Spring Batch 指南

SpringBatch 介绍 目前&#xff0c;Spring Batch是批处理框架界为数不多的优秀框架(Java语言开发)。 Spring Batch 是一个轻量级的、完善的批处理框架,旨在帮助企业建立健壮、高效的批处理应用。 Spring Batch是Spring的一个子项目,使用Java语言并基于Spring框架为基础开发,…

.Net 6.0 部署Linux+Nginx +PM2教程

今天带大家将本地.Net6.0项目部署到Linux系统中,其中有用到Nginx反向代理和PM2进程管理工具,希望本偏文章能对你有所帮助,成为你成功路上的垫脚石! 背景: 在.Net 5.0横空出世之后,.Net已经支持夸平台了,身为一名合格的码农,你敢说你不会用Linux? 哈哈哈开个玩笑,因为工作最近接…

Idea启动运行报错:Error:java: 无效的源发行版: 13

最近在做Springboot项目时&#xff0c;常常出现上述错误&#xff0c;小编也不知道怎么回事&#xff0c;到网上找了这个方面的解决办法&#xff0c;但是却发现根本解决不了&#xff0c;最终通过小编多次尝试&#xff0c;终于发现&#xff0c;为什么会报这个错误。(应该是Java版本…

基于广泛数据增强的新型白质束ONE-SHOT分割

文章目录 One-Shot Segmentation of Novel White Matter Tracts via Extensive Data Augmentation摘要方法One-Shot分割的广泛数据增强 实验结果 One-Shot Segmentation of Novel White Matter Tracts via Extensive Data Augmentation 摘要 探索了新WM束的One-Shot分割问题由…

Kubernetes 如何保障容器可用性?一文介绍探针的使用

有时候&#xff0c;应用因为无限循环或死锁而停止响应&#xff0c;为确保应用在这种情况下可以重新启动&#xff0c;需要有一种机制检查应用程序的运行状况&#xff0c;而不是依赖应用程序内部的检测。 K8s 主要提供了三种探针来针对这种机制&#xff1a; 存活探针&#xff1a…

Swift之深入解析内存安全

一、内存安全 一般来说&#xff0c;Swift 会阻止代码中的不安全行为。例如&#xff0c;Swift 会保证变量在被使用前已经初始化&#xff0c;在释放某变量后其内存也会变得不可访问&#xff0c;以及检查数组索引是否存在越界错误。Swift 还通过要求修改内存中位置的代码具有对该…

通达信缠论顶底分型选股公式(一笔优化版)

在前文《缠论底分型选股公式&#xff0c;处理了包含关系》中介绍了缠论底分型&#xff0c;并编写了选股公式。底分型条件比较容易满足&#xff0c;因此产生的信号比较多。有热心网友提出&#xff0c;可以用顶底分型构成一笔过滤信号。 缠论一笔的构成条件&#xff1a;两个相邻…

砷化镓,锑化铟的能带结构

目录 回顾 正课 1.锑化铟的能带结构 2.砷化镓的能带结构 3.混合晶体的能带结构 回顾 从结合力上看由共价键和离子键混合 化合物半导体从结构上来说具有闪锌矿结构 三五族半导体的能带结构&#xff1a; 1.导带结构 2.价带结构 3.禁带宽度 正课 能带结构的共同特征&#…

docker容器与网络模式|磁盘使用|内存使用|清理

docker容器与网络模式|磁盘使用|内存使用|清理 一 docker 网络模式二 docker的网络模式分类三 网络模式详解3.1host模式&#xff1a;3.2 container模式container模式操作 3.3 none模式3.4 brideg模式3.5 自定义网络 四 容器资源控制4.1 docker容器cpu压力测试4.2 设置CPU资源占…