spring 整合内存缓存LoadingCache
2017-08-31 17:34
417 查看
项目上的服务要频繁的调用图片信息,而大多数又是重复的访问,考虑做成内存级别的细粒度的缓存。
它依赖于两个重要的类来帮助它构建出缓存,首先是CacheBuilder类,通过该类的对象可以设置一些缓存的参数,比如失效时间等。
另一个就是CacheLoader
定义一个抽象类,带有泛型,实现CommandLineRunner接口用于初始化,持有一个只对其子类开放的LoadingCache对象,这样继承了这个抽象类的实现类就持有一个自己定义了泛型的cache对象,而且要实现CommandLineRunner的run方法实现初始化。这样有利于维护扩展。
这里我们实例化一个用来查询图片的实现类。
在run方法里面实例化一个CacheBuilder接口,设定我们要的参数,然后实例化一个CacheLoader对象,在load方法里指定穿透的数据库接口,这里是photoDAO。然后this.cache = cb.build(cl);调用父类的cache引用,构建出缓存。
然后在定义一个方法用来对外服务,方法里面调用cache的get方法查询缓存,如果穿透会去CacheLoader里面指定的接口查询。
由于spring托管的实例都是单例的,在程序启动构建后,可以单例的提供服务。在需要查询的位置通过@Autowired托管即可。
LoadingCache
LoadingCache是google.common.cache下的一个接口,它里面有几个方法,用到的是它的get方法,从缓存取数据。它依赖于两个重要的类来帮助它构建出缓存,首先是CacheBuilder类,通过该类的对象可以设置一些缓存的参数,比如失效时间等。
另一个就是CacheLoader
缓存建立
由于是提供服务的缓存,我们要在服务启动的之前就要构建出缓存的对象,使用spring-boot的CommandLineRunner接口来在程序启动之前建立缓存。之前缓存建立到一个相当于controller层面,但是是以预先加载的方式,这样它缓存的就是service层返回数据的缓存,感觉不合理,就把缓存的建立做到类似service层的地方,也就是缓存的是dao接口返回的结果。这样离数据库更近了一些。public abstract class AbstractCachedServiceImpl<K, V> implements CommandLineRunner { protected LoadingCache<K, V> cache; }
定义一个抽象类,带有泛型,实现CommandLineRunner接口用于初始化,持有一个只对其子类开放的LoadingCache对象,这样继承了这个抽象类的实现类就持有一个自己定义了泛型的cache对象,而且要实现CommandLineRunner的run方法实现初始化。这样有利于维护扩展。
@Component @Order(value = 5) public class PhotoCacheServiceImpl extends AbstractCachedServiceImpl<Integer, PhotoPackage> implements PhotoCacheService { private static final Logger LOGGER = LoggerFactory.getLogger(PhotoCacheServiceImpl.class); @Autowired private PhotoDAO photoDAO; @Override public void run(String... strings) throws Exception { CacheBuilder cb = CacheBuilder.newBuilder().maximumSize(1024).expireAfterWrite(10, HOURS) .initialCapacity(256).concurrencyLevel(256).recordStats(); CacheLoader<Integer, PhotoPackage> cl = new CacheLoader<Integer, PhotoPackage>() { @Override public PhotoPackage load(Integer poiId) throws Exception { PhotoPackage photoPackage = new PhotoPackage(3, 20); List<Photo> list = photoDAO.getPhoto(poiId); LOGGER.info("Cache missed. Try query - key=" + poiId); for (Photo photo : list) { int picId = photo.getPicId(), typeInt = photo.getType(); String copyright = photo.getCopyright(), photoKey = photo.getPhotoKey(); PhotoUtils.buildAndAdd(photoPackage, picId, typeInt, copyright, photoKey); } return photoPackage; } }; this.cache = cb.build(cl); } public PhotoPackage queryPhoto(int id) throws Exception { return this.cache.get(id); } }
这里我们实例化一个用来查询图片的实现类。
在run方法里面实例化一个CacheBuilder接口,设定我们要的参数,然后实例化一个CacheLoader对象,在load方法里指定穿透的数据库接口,这里是photoDAO。然后this.cache = cb.build(cl);调用父类的cache引用,构建出缓存。
然后在定义一个方法用来对外服务,方法里面调用cache的get方法查询缓存,如果穿透会去CacheLoader里面指定的接口查询。
由于spring托管的实例都是单例的,在程序启动构建后,可以单例的提供服务。在需要查询的位置通过@Autowired托管即可。
相关文章推荐
- spring boot整合shiro后,部分注解(Cache缓存、Transaction事务等)失效的问题
- 缓存 SpringModules Cache ( spring 和 ehcache的整合 ) spring提供缓存bean方案
- 缓存 SpringModules Cache ( spring 和 ehcache的整合 ) spring提供缓存bean方案(转载)
- spring3 自带 cache 整合之方法缓存
- SpringBoot 整合redis实现缓存 记录@CachePut值为1
- Redis整合Spring结合使用缓存实例
- 2.0Spring整合Ehcache管理缓存
- Ehcache 整合Spring 使用页面、对象缓存
- Spring缓存注解@Cacheable,@CachePut , @CacheEvict使用
- spring整合redis缓存,以注解(@Cacheable、@CachePut、@CacheEvict)形式使用
- spring 缓存 @CachePut 和 @Cacheable 区别
- spring整合redis客户端及缓存接口设计
- Spring Boot 整合 Redis 实现缓存操作
- 8 -- 深入使用Spring -- 5...2 使用@Cacheable执行缓存
- Spring Boot 整合 Redis 实现缓存操作
- hibernate4整合spring3.1出现java.lang.NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider
- Ehcache 整合Spring 使用页面、对象缓存
- Spring缓存注解@Cache,@CachePut , @CacheEvict,@CacheConfig使用
- spring-boot整合redis作为mysql二级缓存
- spring boot guava cache 缓存学习