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); }}
注入
形式一
- 新建一个枚举类
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; }}
- 注入到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
生效,注解生效。
解决办法
- 办法用
public
限定符润饰; - 类外部办法调用加缓存时能够用
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); }}