Caffeine简介

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

依赖

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-cache</artifactId></dependency><dependency>    <groupId>com.github.ben-manes.caffeine</groupId>    <artifactId>caffeine</artifactId></dependency>

开启缓存

@EnableCaching注解开启应用缓存治理性能

@SpringBootApplication@EnableCachingpublic 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容器
    /**     * 本地缓存     * @return     */    @Bean    @Primary    public CacheManager cacheManager() {        SimpleCacheManager simpleCacheManager = new SimpleCacheManager();        ArrayList<CaffeineCache> 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@Primarypublic CacheManager cacheManager() {    CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();    Caffeine<Object, Object> 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

@Componentpublic 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> T getBean(Class<T> clazz) {        return applicationContext.getBean(clazz);    }    public static <T> T getBean(String name, Class<T> 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<? extends Object> getType(String name) {        return applicationContext.getType(name);    }}