2013-10-31 44 views
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每個方法!

我嘗試將所有內容整合到一個單一的CacheLoader中,該單元返回Object類型並接受一個Map對象,但最後我得到了很大的難看的if/else來找出調用哪個方法來加載緩存。

我正在努力尋找一種優雅的方式來爲這些數據訪問對象添加緩存,有什麼建議嗎?也許番石榴緩存不適合這種用例?

回答

4

試試這個。不幸的是,由於泛型,有編譯器警告......但是我們可能會禁止它們,因爲我們知道什麼都不會發生。

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

以同樣的方式的其他方法。我認爲你不能再減少樣板。

+0

漂亮!謝謝。 – Upgradingdave

+0

很高興我能幫忙:) – siledh

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.