您的位置:首页 > 编程语言 > Java开发

spring 整合内存缓存LoadingCache

2017-08-31 17:34 417 查看
项目上的服务要频繁的调用图片信息,而大多数又是重复的访问,考虑做成内存级别的细粒度的缓存。

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托管即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: