集成
javax.cache.integration包中包含集成外部资源的类。
缓存数据加载
Cache的loadAll方法用于从外部资源中加载数据。定义如下。
void loadAll(Set<? extends K> keys,boolean replaceExistingValues,
CompletionListenercompletionListener);
对于此方法中使用的CacheLoader必须在缓存创建时已经在配置中设置。缓存使用此方法并不需要被设置为read-through缓存模式。
数据加载可能需要大量的时间,基于这个原因,可以通过CompletionListener其中在完成或异常时收到通知。它的定义如下:
public interface CompletionListener {
/**
* 通知应用程序操作成功完成。
*/
void onCompletion();
/**
* 通知应用程序操作失败。
*/
void onException(Exception e);
}
另外提供了阻塞式的CompletionListener实现CompletionListenerFuture,它实现了CompletionListener和Future两个接口。如果CompletionListener的onException(Exceptione)方法被调用,则异常被包装成ExecutionException,然后被Future的get()和get(long timeout, TimeUnit unit)方法抛出。
例子1:使用CompletionListenerFuture。
HashSet<String> keys = new HashSet<>();
keys.add("23432lkj");
keys.add("4fsdldkj");
//创建一个CompletionListenerFuture然后等待loadAll完成
CompletionListenerFuture future = new CompletionListenerFuture();
//加载keys集合的所有值,值存在时替换旧值
cache.loadAll(keys, true, future);
//等待值加载完成
try {
future.get();
}catch (InterruptedException e) {
//future interrupted
e.printStackTrace();
}catch (ExecutionException e) {
//抛出的是被送到onException(Exception e)方法的异常
Throwable throwable = e.getCause();
}
loadAll方法的用途是从外部资源预加载数据到缓存中,这对于应用程序来说如果数据在缓存外需要加载是很有必要的。另一种用途是缓存预热,如果数据在缓存中不存在,并不会导致应用程序错误,但它会影响性能或可伸缩性。
缓存的Read-Through
除了缓存条目不存在时,需要调用CacheLoader加载数据外,read-through的缓存和非read-through缓存的行为是完全相同的。
缓存Read-Through是在配置时通过调用setReadThrough(boolean isReadThrough)设置到MutableConfiguration上来实现的,一个CacheLoader工厂也同时必须被定义。CacheLoader用于从外部资源加载缓存条目。
当缓存处于read-through模式下时每个方法调用的效果如下表所述:
方法 |
是否调用Read-Through |
boolean containsKey(K key) |
否 |
V get(K key) |
是 |
Map<K,V> getAll(Collection<? extends K> keys) |
是,调用loadAll() |
V getAndPut(K key, V value) |
否 |
V getAndRemove(K key) |
否 |
V getAndReplace(K key, V value) |
否 |
<T> T invoke(K key, EntryProcessor<K, V, T> entryProcessor, Object... arguments)entryProcessor); |
是,如果getValue() 被调用 |
<T> Map<K, T> invokeAll(Set<? extends K> keys, EntryProcessor<K, V, T> entryProcessor, Object... arguments); |
是,如果getValue() 被调用 |
Iterator<Cache.Entry<K, V>> iterator() |
否 |
void loadAll(Set<? extends K> keys, boolean replaceExistingValues, CompletionListener completionListener)
|
是,使用CacheLoader.loadAll() 方法,即时缓存不是read-through模式 |
void put(K key, V value) |
否 |
void putAll(Map<? extends K,? extends V> map) |
否 |
boolean putIfAbsent(K key, V value) |
否 |
boolean remove(K key) |
否 |
boolean remove(K key, V oldValue) |
否 |
void removeAll() |
否 |
void removeAll(Set<? extends K> keys) |
否 |
boolean replace(K key, V value) |
否 |
boolean replace(K key, V oldValue, V newValue) |
否 |
缓存Read-through是懒加载缓存数据的一个有用的术语,这对于屏蔽来自外部的资源是如何加载到缓存中的细节非常有用。
当想预加载一些或所有缓存数据到缓存中时,使用loadAll方法。
缓存的Write-Through
除了一些可变的方法将调用CacheWriter外,缓存write-through的行为和非write-through完全一样。
缓存Write-Through是在配置时通过调用setWriteThrough(booleanisWriteThrough)设置到MutableConfiguration上来实现的,一个CacheWriter工厂也同时必须被定义。CacheWriter用于写入缓存条目到外部资源和从外部资源删除缓存条目。
当缓存处于write-through模式下时每个方法调用的效果如下表所述:
方法 |
是否调用Write-Through |
boolean containsKey(K key) |
否 |
V get(K key) |
否 |
Map<K,V> getAll(Collection<? extends K> keys) |
否 |
V getAndPut(K key, V value) |
是 |
V getAndRemove(K key) |
是 |
V getAndReplace(K key, V value) |
是 |
<T> T invoke(K key, EntryProcessor<K, V, T> entryProcessor, Object... arguments) |
是,如果setValue () 被调用 |
<T> Map<K, T> invokeAll(Set<? extends K> keys, EntryProcessor<K, V, T> entryProcessor, Object... arguments); |
是,如果setValue () 被调用 |
Iterator<Cache.Entry<K, V>> iterator() |
否 |
void loadAll(Set<? extends K> keys, boolean replaceExistingValues, CompletionListener completionListener) |
否 |
void put(K key, V value) |
是 |
void putAll(Map<? extends K,? extends V> map) |
是,writeAll将被调用 |
boolean putIfAbsent(K key, V value) |
是,如果该方法返回true |
boolean remove(K key) |
是 |
boolean remove(K key, V oldValue) |
是,如果该方法返回true |
void removeAll() |
是 |
void removeAll(Set<? extends K> keys) |
是 |
boolean replace(K key, V value) |
是 |
boolean replace(K key, V oldValue, V newValue) |
是,如果该方法返回true |
缓存Write-through是懒更新缓存数据变化到外部资源的一个有用的惯用语,这对于屏蔽缓存如何写入数据到外部资源的细节非常有用。