栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Cache + Caffeine实现本地缓存

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Cache + Caffeine实现本地缓存

Spring Cache + Caffeine实现本地缓存 Caffeine简介

Caffeine是一个高性能,高命中率,低内存占用,near optimal 的本地缓存,简单来说它是 Guava Cache 的优化加强版

依赖

    org.springframework.boot
    spring-boot-starter-cache


    com.github.ben-manes.caffeine
    caffeine

开启缓存

@EnableCaching注解开启使用缓存管理功能

@SpringBootApplication
@EnableCaching
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
注入 方式一
  1. 新建一个枚举类
public enum Caches {
    CACHE_ACCESS_TOKEN(10, 7200);

    
    private Integer maxSize;

    
    private Integer ttl;

    Caches() {
    }

    Caches(Integer maxSize, Integer ttl) {
        this.maxSize = maxSize;
        this.ttl = ttl;
    }

    public Integer getMaxSize() {
        return maxSize;
    }

    public Integer getTtl() {
        return ttl;
    }

}
  1. 注入到IOC容器
    
    @Bean
    @Primary
    public CacheManager cacheManager() {
        SimpleCacheManager simpleCacheManager = new SimpleCacheManager();

        ArrayList caffeineCaches = new ArrayList<>();

        for (Caches c : Caches.values()) {
            caffeineCaches.add(new CaffeineCache(c.name(),
                            Caffeine.newBuilder()
                                    .recordStats()
                                    .expireAfterWrite(c.getTtl(), TimeUnit.SECONDS)
                                    .maximumSize(c.getMaxSize())
                                    .build()
                    )
            );
        }

        simpleCacheManager.setCaches(caffeineCaches);
        return simpleCacheManager;

    }
方式二
@Bean
@Primary
public CacheManager cacheManager() {

    CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
    Caffeine caffeine = Caffeine.newBuilder().expireAfterWrite(60, TimeUnit.MINUTES);
    caffeineCacheManager.setCaffeine(caffeine);
    return caffeineCacheManager;

}
使用

可以使用spring提供的@Cacheable、@CachePut、@CacheEvict等注解来方便的使用caffeine缓存

@Cacheable(cacheNames = "CACHE_ACCESS_TOKEN", key = "#root.methodName")
public String getAccessToken(String corpid, String corpsecret) {

   //todo something...
   return "";

}
问题 使用@Cacheable缓存不起作用

失效场景

  • 在私有方法上加缓存
  • 类内部方法调用加缓存

失效原因

Spring cache 的实现原理是基于 AOP 的动态代理实现的:即都在方法调用前后去获取方法的名称、参数、返回值,然后根据方法名称、参数生成缓存的key(自定义的key例外),进行缓存。

AOP 不支持对 private 私有方法的拦截,所以也就不支持私有方法上的 Spring Cache 注解。

this 调用不是代理对象的调用, 所以 AOP 失效,注解失效。

解决办法

  1. 方法用 public 限定符修饰;
  2. 类内部方法调用加缓存时可以用 SpringContextUtil 获取当前 Bean ,由它来调用
工具类

SpringContextUtil

@Component
public class SpringContextUtil implements ApplicationContextAware {

    public static ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextUtil.applicationContext = applicationContext;
    }

    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    public static  T getBean(Class clazz) {
        return applicationContext.getBean(clazz);
    }

    public static  T getBean(String name, Class clazz) {
        return applicationContext.getBean(name, clazz);
    }

    public static Boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }

    public static Boolean isSingleton(String name) {
        return applicationContext.isSingleton(name);
    }

    public static Class getType(String name) {
        return applicationContext.getType(name);
    }


}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/888385.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号