0


spring cache 详解

系列文章目录


文章目录


前言

伴随信息量的爆炸式增长以及构建的应用系统越来越多样化、复杂化,特别是企业级应用互联网化的趋势,缓存(Cache)对应用程序性能的优化变的越来越重要。 将所需服务请求的数据放在缓存中,既可以提高应用程序的访问效率,又可以减少数据库服务器的压力,从而让用户获得更好的用户体验。


一、spring cache

1、简介

定义了 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术,并支持使用 JCache(JSR-107)注解简化我们开发。SpringCache本质上不是一种缓存的实现,而是一种缓存的抽象。通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果

2、注解使用

在这里插入图片描述

1、@Cacheable

先查询是否已经有缓存,有会使用缓存,没有则会执行方法并缓存。注意:要缓存的实体类必须实现序列化。一般用于查找
在这里插入图片描述

2、@CachePut

和 @Cacheable 不同的是,它每次都会触发真实方法的调用 。简单来说就是用户更新缓存数据。
在这里插入图片描述

3、@CacheEvict

作用:主要针对方法配置,能够根据一定的条件对缓存进行清空 。一般用于删除和更新。
在这里插入图片描述

4、@Caching

@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解

@Caching(evict={@CacheEvict("user1"),@CacheEvict("user2",allEntries=true)})

在这里插入图片描述

5、@CacheConfig

@CacheConfig是一个类级别的注解,它允许共享缓存名称,自定义KeyGenerator,自定义CacheManager和自定义CacheResolver。

在这里插入图片描述
当我们需要缓存的地方越来越多,可以在类上使用 @CacheConfig(cacheNames = {“”}) 注解来统一指定 value 的值,这时方法可省略 value,如果你在你的方法依旧写上了 value,那么依然以方法的value值为准

@CacheConfig(cacheNames ={"myCache"})publicclassUserServiceImplimplementsUserService{@Override@Cacheable(key ="targetClass + methodName + #p0")//此处没写valuepublicList<User>findAllLimit(int num){return userRepository.findAllLimit(num);}.....}
  • Spring支持的CacheManager,
  • SimpleCache:没有引入其他缓存组件的情况下,SpringBoot 的默认缓存,使用ConcurrentMap实现.

在这里插入图片描述

3、注意点

  • 配置文件中启用缓存:spring.cache.type=redis
  • 缓存的对象必须实现Serializable 注解是基于Spring
  • AOP代理类,内部方法调用是不走代理的,注解是不起作用的

4、spring cache 优劣

优势

  • 支持开箱即用(Out Of The Box),并提供基本的Cache抽象,方便切换各种底层Cache
  • 通过Cache注解即可实现缓存逻辑透明化,让开发者关注业务逻辑
  • 当事务回滚时,缓存也会自动回滚
  • 支持比较复杂的缓存逻辑
  • 提供缓存编程的一致性抽象,方便代码维护。

劣势

  • Spring Cache并不针对多进程的应用环境进行专门的处理。
  • 另外SpringCache抽象的操作中没有锁的概念,当多线程并发操作(更新或者删除)同一个缓存项时,有可能读取到过期的数据。
  • 查询是加锁,其他的都是公用的没有加锁。读模式做了处理,写模式并没有管 常规(读多写少,及时性,一致性不高的数据完全可以用SpringCache)

场景问题处理

1、问题处理场景一
2、问题处理场景二
3、问题处理场景三

二、集成springboot

1、maven依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.70</version></dependency>

2、 配置文件

 redis:
    host: 主机ip地址
    port: 6379
    password: '密码'
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 500
        min-idle: 0
    lettuce:
      shutdown-timeout: 30000

3、启动类配置

 在启动类上添加**@EnableCaching,开始缓存**

4、编写配置类

importcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.parser.ParserConfig;importcom.alibaba.fastjson.serializer.SerializerFeature;importcom.fasterxml.jackson.databind.ObjectMapper;importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;importorg.springframework.boot.autoconfigure.data.redis.RedisProperties;importorg.springframework.boot.context.properties.EnableConfigurationProperties;importorg.springframework.cache.Cache;importorg.springframework.cache.CacheManager;importorg.springframework.cache.annotation.CachingConfigurerSupport;importorg.springframework.cache.annotation.EnableCaching;importorg.springframework.cache.interceptor.CacheErrorHandler;importorg.springframework.cache.interceptor.KeyGenerator;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.cache.RedisCacheConfiguration;importorg.springframework.data.redis.cache.RedisCacheManager;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.data.redis.serializer.*;importjava.lang.reflect.Method;importjava.nio.charset.Charset;importjava.time.Duration;@Slf4j@Configuration@EnableCaching@EnableConfigurationProperties(RedisProperties.class)publicclassCacheConfigextendsCachingConfigurerSupport{privatestaticfinalFastJsonRedisSerializer<Object> fastJsonRedisSerializer =newFastJsonRedisSerializer<>(Object.class);//缓存管理器。可以管理多个缓存//只有CacheManger才能扫描到cacheable注解//spring提供了缓存支持Cache接口,实现了很多个缓存类,其中包括RedisCache。但是我们需要对其进行配置,这里就是配置RedisCache@BeanpublicCacheManagercacheManager(RedisConnectionFactory connectionFactory){RedisCacheManager cacheManager =RedisCacheManager.RedisCacheManagerBuilder//Redis链接工厂.fromConnectionFactory(connectionFactory)//缓存配置 通用配置  默认存储一小时.cacheDefaults(getCacheConfigurationWithTtl(Duration.ofHours(1)))//配置同步修改或删除  put/evict.transactionAware()//对于不同的cacheName我们可以设置不同的过期时间//                .withCacheConfiguration("app:",getCacheConfigurationWithTtl(Duration.ofHours(5))).withCacheConfiguration("user:",getCacheConfigurationWithTtl(Duration.ofHours(2))).build();return cacheManager;}//缓存的基本配置对象privateRedisCacheConfigurationgetCacheConfigurationWithTtl(Duration duration){returnRedisCacheConfiguration.defaultCacheConfig()//设置key value的序列化方式// 设置key为String.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(newStringRedisSerializer()))// 设置value 为自动转Json的Object.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer))// 不缓存null.disableCachingNullValues()// 设置缓存的过期时间.entryTtl(duration);}//缓存的异常处理@Bean@OverridepublicCacheErrorHandlererrorHandler(){// 异常处理,当Redis发生异常时,打印日志,但是程序正常走
        log.info("初始化 -> [{}]","Redis CacheErrorHandler");returnnewCacheErrorHandler(){@OverridepublicvoidhandleCacheGetError(RuntimeException e,Cache cache,Object key){
                log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);}@OverridepublicvoidhandleCachePutError(RuntimeException e,Cache cache,Object key,Object value){
                log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);}@OverridepublicvoidhandleCacheEvictError(RuntimeException e,Cache cache,Object key){
                log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);}@OverridepublicvoidhandleCacheClearError(RuntimeException e,Cache cache){
                log.error("Redis occur handleCacheClearError:", e);}};}@Override@Bean("myKeyGenerator")publicKeyGeneratorkeyGenerator(){returnnewKeyGenerator(){@OverridepublicObjectgenerate(Object target,Method method,Object... params){StringBuffer sb =newStringBuffer();
                sb.append(target.getClass().getName());
                sb.append(method.getName());for(Object obj : params){
                    sb.append(obj.toString());}return sb.toString();}};}}

5、编写代码

@ServicepublicclassUserImplimplementsUserService{@ResourceprivateUsersMapper usersMapper;@OverridepublicUserqueryNo(Integer userId){System.out.println("进入无缓存方法");User user = usersMapper.queryUser(userId);return user;}/**
     * 查找缓存
     * @param userId userID
     * @return user
     */@Override@Cacheable(cacheNames ="user",key = "#userId)publicUserquery(Integer userId){System.out.println("进入有缓存方法");return usersMapper.queryUser(userId);}}
标签: spring java 后端

本文转载自: https://blog.csdn.net/qq_39239864/article/details/137678520
版权归原作者 Gary董 所有, 如有侵权,请联系我们删除。

“spring cache 详解”的评论:

还没有评论