0

我有几十个像 PersonDao 这样的数据访问对象,其方法如下:

Person findById(String id) {}
List<Person> search(String firstName, LastName, Page) {}
int searchCount(String firstName, LastName) {}

我已经尝试通过在其中一个类中添加番石榴缓存,这非常好,但是有很多样板。

这是一个先在缓存中查找 findById 的示例:

private final LoadingCache<String, Person> cacheById = CacheBuilder.newBuilder()
  .maximumSize(maxItemsInCache)
  .expireAfterWrite(cacheExpireAfterMinutes, TimeUnit.MINUTES)
  .build(new CacheLoader<String, Person>() {
    public Person load(String key) {
      return findByIdNoCache(key);
  });
//.... and update findById to call the cache ...
@Override
public Person findById(String id) {
  return cacheById.getUnchecked(id);
}

所以,因为每个方法都有不同的参数和返回类型,我最终为每个方法创建了一个单独的 cacheLoader!

我尝试将所有内容合并到一个返回 Object 类型并接受对象 Map 的单个 CacheLoader 中,但最终我得到了一个丑陋的 if/else 来确定调用哪个方法来加载缓存。

我正在努力寻找一种优雅的方式来为这些数据访问对象添加缓存,有什么建议吗?也许番石榴缓存不适合这个用例?

4

2 回答 2

5

试试这个。不幸的是,由于泛型存在编译器警告......但我们可能会抑制它们,因为我们知道不会发生任何不好的事情。

public class CacheContainer {

    private static final long maxItemsInCache = 42;
    private static final long cacheExpireAfterMinutes = 42;
    private final Map<String, LoadingCache> caches = Maps.newHashMap();


    public <K, V> V getFromCache(String cacheId, K key, CacheLoader<K, V> loader) throws ExecutionException {
        LoadingCache<K, V> cache = caches.get(cacheId);
        if (cache == null) {
            cache = CacheBuilder.newBuilder().
                     maximumSize(maxItemsInCache).
                     expireAfterWrite(cacheExpireAfterMinutes, TimeUnit.MINUTES).
                     build(loader);
            caches.put(cacheId, cache);
        }
        return cache.get(key);
    }
}

然后在你的道中:

private final CacheContainer cacheContainer = new CacheContainer();


public Person findById(String id) {
    cacheContainer.getFromCache("personById", id, new CacheLoader<String, Person>() {
        @Override
        public Person load(String key) {
          return findByIdNoCache(key);
      });
}

其他方法同理。我认为您不能减少样板文件。

于 2013-10-31T17:08:09.280 回答
1

CacheLoader为每个要缓存结果的方法创建一个(和单独的缓存)是必要的。您可以通过使用所需的缓存配置创建单个CacheBuilder缓存,然后像这样创建每个缓存来简化一些事情:

private final CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder()
    .maximumSize(maxItemsInCache)
    .expireAfterWrite(cacheExpireAfterMinutes, TimeUnit.MINUTES);

private final LoadingCache<String, Person> cacheById = builder.build(
    new CacheLoader<String, Person>() {
      // ...
    });

 private final LoadingCache<Search, List<Person>> searchCache = builder.build(
     new CacheLoader<Search, List<Person>>() {
       // ...
     });

  // etc.
于 2013-10-31T18:02:03.167 回答