【问题标题】:Ways to reduce boilerplate using guava cache使用番石榴缓存减少样板的方法
【发布时间】:2013-10-31 16:36:33
【问题描述】:

我有几十个像 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!

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

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

【问题讨论】:

    标签: java caching guava


    【解决方案1】:

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

    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);
          });
    }
    

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

    【讨论】:

      【解决方案2】:

      需要为每个要缓存结果的方法创建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.
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-27
        相关资源
        最近更新 更多