spring 整合内存缓存LoadingCache

来源:互联网 发布:网络棋牌平台排名2017 编辑:程序博客网 时间:2024/05/23 00:12

项目上的服务要频繁的调用图片信息,而大多数又是重复的访问,考虑做成内存级别的细粒度的缓存。

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托管即可。


原创粉丝点击