* {@link Cache}s produced and owned by a {@link CacheManager} typically share * common infrastructure, for example, a common {@link ClassLoader} and * implementation specific {@link Properties}. *
* Implementations of {@link CacheManager} may additionally provide and share * external resources between the {@link Cache}s being managed, for example, * the content of the managed {@link Cache}s may be stored in the same cluster. *
* By default {@link CacheManager} instances are typically acquired through the * use of a {@link CachingProvider}. Implementations however may additionally * provide other mechanisms to create, acquire, manage and configure * {@link CacheManager}s, including: *
new operator to create a
* concrete implementation, * The default {@link CacheManager} however can always be acquired using the * default configured {@link CachingProvider} obtained by the {@link Caching} * class. For example: *
* CachingProvider provider = Caching.getCachingProvider();
* CacheManager manager = provider.getCacheManager();
*
*
* Within a Java process {@link CacheManager}s and the {@link Cache}s they
* manage are scoped and uniquely identified by a {@link URI}, the meaning of
* which is implementation specific. To obtain the default {@link URI},
* {@link ClassLoader} and {@link Properties} for an implementation, consult the
* {@link CachingProvider} class.
*
*
* @author Greg Luck
* @author Yannis Cosmadopoulos
* @author Brian Oliver
* @see Caching
* @see CachingProvider
* @see Cache
* @since 1.0
*
*/
public interface CacheManager extends Closeable {
/**
* Get the {@link CachingProvider} that created and is responsible for
* the {@link CacheManager}.
*
* @return the CachingProvider or null if the {@link CacheManager}
* was created without using a {@link CachingProvider}
*/
CachingProvider getCachingProvider();
/**
* Get the URI of the {@link CacheManager}.
*
* @return the URI of the {@link CacheManager}
*/
URI getURI();
/**
* Get the {@link ClassLoader} used by the {@link CacheManager}.
*
* @return the {@link ClassLoader} used by the {@link CacheManager}
*/
ClassLoader getClassLoader();
/**
* Get the {@link Properties} that were used to create this
* {@link CacheManager}.
*
* Implementations are not required to re-configure the * {@link CacheManager} should modifications to the returned * {@link Properties} be made. * * @return the Properties used to create the {@link CacheManager} */ Properties getProperties(); /** * Creates a named {@link Cache} at runtime. *
* If a {@link Cache} with the specified name is known to the {@link * CacheManager}, a CacheException is thrown. *
* If a {@link Cache} with the specified name is unknown the {@link * CacheManager}, one is created according to the provided {@link Configuration} * after which it becomes managed by the {@link CacheManager}. *
* Prior to a {@link Cache} being created, the provided {@link Configuration}s is * validated within the context of the {@link CacheManager} properties and * implementation. *
* Implementers should be aware that the {@link Configuration} may be used to * configure other {@link Cache}s. *
* There's no requirement on the part of a developer to call this method for
* each {@link Cache} an application may use. Implementations may support
* the use of declarative mechanisms to pre-configure {@link Cache}s, thus
* removing the requirement to configure them in an application. In such
* circumstances a developer may simply call either the
* {@link #getCache(String)} or {@link #getCache(String, Class, Class)}
* methods to acquire a previously established or pre-configured {@link Cache}.
*
* @param
* Use this method to check runtime key and value types.
*
* Use {@link #getCache(String)} where this check is not required.
*
* Implementations must ensure that the key and value types are the same as
* those configured for the {@link Cache} prior to returning from this method.
*
* Implementations may further perform type checking on mutative cache operations
* and throw a {@link ClassCastException} if these checks fail.
*
* Implementations that support declarative mechanisms for pre-configuring
* {@link Cache}s may return a pre-configured {@link Cache} instead of
*
* This method may only be used to acquire {@link Cache}s that were
* configured without runtime key and value types, or were configured
* to use Object.class key and value types.
*
* Use the {@link #getCache(String, Class, Class)} method to acquire
* {@link Cache}s with a check that the supplied key and value type parameters
* match the runtime types.
*
* Implementations that support declarative mechanisms for pre-configuring
* {@link Cache}s may return a pre-configured {@link Cache} instead of
*
* {@link java.util.Iterator}s returned by the {@link Iterable} are immutable.
* If the {@link Cache}s managed by the {@link CacheManager} change,
* the {@link Iterable} and associated {@link java.util.Iterator}s are not
* affected.
*
* {@link java.util.Iterator}s returned by the {@link Iterable} may not provide
* all of the {@link Cache}s managed by the {@link CacheManager}. For example:
* Internally defined or platform specific {@link Cache}s that may be accessible
* by a call to {@link #getCache(String)} or {@link #getCache(String, Class,
* Class)} may not be present in an iteration.
*
* @return an {@link Iterable} over the names of managed {@link Cache}s.
* @throws IllegalStateException if the {@link CacheManager}
* is {@link #isClosed()}
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
Iterable
* This is equivalent to the following sequence of method calls:
*
* From the time this method is called, the specified {@link Cache} is not
* available for operational use. An attempt to call an operational method on
* the {@link Cache} will throw an {@link IllegalStateException}.
*
* @param cacheName the cache to destroy
* @throws IllegalStateException if the {@link CacheManager}
* {@link #isClosed()}
* @throws NullPointerException if cacheName is null
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
void destroyCache(String cacheName);
/**
* Controls whether management is enabled. If enabled the {@link CacheMXBean}
* for each cache is registered in the platform MBean server. The platform
* MBeanServer is obtained using
* {@link ManagementFactory#getPlatformMBeanServer()}.
*
* Management information includes the name and configuration information for
* the cache.
*
* Each cache's management object must be registered with an ObjectName that
* is unique and has the following type and attributes:
*
* Type:
*
* Required Attributes:
*
* Each cache's statistics object must be registered with an ObjectName that
* is unique and has the following type and attributes:
*
* Type:
*
* Required Attributes:
*
* For each {@link Cache} managed by the {@link CacheManager}, the
* {@link Cache#close()} method will be invoked, in no guaranteed order.
*
* If a {@link Cache#close()} call throws an exception, the exception will be
* ignored.
*
* After executing this method, the {@link #isClosed()} method will return
*
* All attempts to close a previously closed {@link CacheManager} will be
* ignored.
*
* Closing a CacheManager does not necessarily destroy the contents of the
* Caches in the CacheManager.
*
* It simply signals that the CacheManager is no longer required by the application
* and that future uses of a specific CacheManager instance should not be permitted.
*
* Depending on the implementation and Cache topology,
* (e.g. a storage-backed or distributed cache), the contents of closed Caches
* previously referenced by the CacheManager, may still be available and accessible
* by other applications.
*
* @throws SecurityException when the operation could not be performed due to the
* current security settings
*/
void close();
/**
* Determines whether the {@link CacheManager} instance has been closed. A
* {@link CacheManager} is considered closed if;
*
* This method generally cannot be called to determine whether the
* {@link CacheManager} is valid or invalid. A typical client can determine
* that a {@link CacheManager} is invalid by catching any exceptions that
* might be thrown when an operation is attempted.
*
* @return true if this {@link CacheManager} instance is closed; false if it
* is still open
*/
boolean isClosed();
/**
* Provides a standard mechanism to access the underlying concrete caching
* implementation to provide access to further, proprietary features.
*
* If the provider's implementation does not support the specified class,
* the {@link IllegalArgumentException} is thrown.
*
* @param
* The properties provided by instances of this interface are used by
* {@link CacheManager}s to configure {@link Cache}s.
*
* Implementations of this interface must override {@link Object#hashCode()} and
* {@link Object#equals(Object)} as {@link Configuration}s are often compared at
* runtime.
*
* @param
* When false, both keys and values are stored by reference.
* Caches stored by reference are capable of mutation by any threads holding
* the reference. The effects are:
*
* When a cache is storeByValue, any mutation to the key or value does not
* affect the key of value stored in the cache.
*
* The default value is
* The properties provided by instances of this interface are used by
* {@link javax.cache.CacheManager}s to configure {@link javax.cache.Cache}s.
*
* Implementations of this interface must override {@link Object#hashCode()} and
* {@link Object#equals(Object)} as
* {@link javax.cache.configuration.CompleteConfiguration}s are often compared at
* runtime.
*
* @param
* When in "read-through" mode, cache misses that occur due to cache entries
* not existing as a result of performing a "get" will appropriately
* cause the configured {@link javax.cache.integration.CacheLoader} to be
* invoked.
*
* The default value is
* When in "write-through" mode, cache updates that occur as a result of
* performing "put" operations called via one of
* {@link javax.cache.Cache#put(Object, Object)},
* {@link javax.cache.Cache#getAndRemove(Object)},
* {@link javax.cache.Cache#removeAll()},
* {@link javax.cache.Cache#getAndPut(Object, Object)}
* {@link javax.cache.Cache#getAndRemove(Object)},
* {@link javax.cache.Cache#getAndReplace(Object,
* Object)}, {@link javax.cache.Cache#invoke(Object,
* javax.cache.processor.EntryProcessor,
* Object...)}, {@link javax.cache.Cache#invokeAll(java.util.Set,
* javax.cache.processor.EntryProcessor, Object...)} will appropriately cause
* the configured {@link javax.cache.integration.CacheWriter} to be invoked.
*
* The default value is
* The default value is
* The default value is
* A CacheLoader should be configured for "Read Through" caches to load values
* when a cache miss occurs using either the
* {@link javax.cache.Cache#get(Object)} and/or
* {@link javax.cache.Cache#getAll(java.util.Set)} methods.
*
* The default value is
* The default value is
* The default value is a {@link javax.cache.configuration.Factory} that will
* produce a {@link javax.cache.expiry.EternalExpiryPolicy} instance.
*
* @return the {@link javax.cache.configuration.Factory} for
* {@link javax.cache.expiry.ExpiryPolicy} (must not be
* Creates a default configuration. Default configurations have no
* runtime type checking and are set for eternal expiry.
*
* To enable runtime type enforcement, if supported by the implementation, call
* {@link #setTypes} after construction.
*
* After construction set any other configuration parameters in the
* fluent style. e.g.
*
* This is used by {@link CacheManager} to ensure that the key and value
* types are the same as those configured for the {@link Cache} prior to
* returning a requested cache from this method.
*
* Implementations may further perform type checking on mutative cache operations
* and throw a {@link ClassCastException} if these checks fail.
*
* @param keyType the expected key type
* @param valueType the expected value type
* @return the {@link MutableConfiguration} to permit fluent-style method calls
* @throws NullPointerException should the key or value type be null
* @see CacheManager#getCache(String, Class, Class)
*/
public MutableConfiguration
* Only one expiry policy can be set for a cache. The last policy applied
* before cache construction will be the one used.
* @param factory the {@link ExpiryPolicy} {@link Factory}
* @return the {@link MutableConfiguration} to permit fluent-style method calls
*/
public MutableConfiguration
* It is an invalid configuration to set this to true without specifying a
* {@link CacheLoader} {@link Factory}.
*
* @param isReadThrough
* It is an invalid configuration to set this to true without specifying a
* {@link CacheWriter} {@link Factory}.
*
* @param isWriteThrough
* Statistics may be enabled or disabled at runtime via
* {@link CacheManager#enableStatistics(String, boolean)}.
*
* @param enabled true to enable statistics, false to disable.
* @return the {@link MutableConfiguration} to permit fluent-style method calls
*/
public MutableConfiguration
* Management may be enabled or disabled at runtime via
* {@link CacheManager#enableManagement(String, boolean)}.
*
* @param enabled true to enable statistics, false to disable.
* @return the {@link MutableConfiguration} to permit fluent-style method calls
*/
public MutableConfiguration
* This is equivalent to the following sequence of method calls:
*
* From the time this method is called, the specified {@link Cache} is not
* available for operational use. An attempt to call an operational method on
* the {@link Cache} will throw an {@link IllegalStateException}.
*
* @param cacheName the cache to destroy
* @throws IllegalStateException if the {@link CacheManager}
* {@link #isClosed()}
* @throws NullPointerException if cacheName is null
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
void destroyCache(String cacheName);
```
一旦被销毁:
- 任何试图操作操作该缓存的方法调用将抛出 `IllegalStateException`
- 被销毁的缓存的名字可以被新缓存重用,跟之前的区别是配置不同。
一旦销毁,就无法通过 `CacheManager` 使用缓存。 销毁缓存可确保关闭缓存,并且无论应用程序或拓扑如何,所有应用程序都将立即或将来不再使用所有关联条目。
### 关闭 `CacheManager`
可以通过 `CacheManager.close()` 或者 `CachingProvider.close(...)` 方法来关闭 `CacheManager`,这两个方法调用会有如下效果:
- 关闭被其管理的所有 `Cache`。
- 释放用来管理 `Cache` 的所有资源。
- 一旦关闭,任何试图操作 `CacheManager` 或其管理的 `Cache` 的行为都将抛出 `IllegalStateException`,其中涉及的方法如下:
```java
- createCache
- destroyCache
- enableManagement
- enableStatistics
- getCache
- getCacheNames
```
关闭 `CacheManager` 后,可以使用最初创建 `CacheManager` 的 `CachingProvider` 创建另外一个实例。这部分将在 `CachingProvder` 部分进行介绍。
关闭 `CacheManager` 并不一定会销毁 `CacheManager` 中 `Cache` 里的数据。 它只是表明应用程序不再需要拥有的`CacheManager`,并且不应再允许该特定 `CacheManager` 实例的将来使用。 取决于实现(基于存储或分布式),已关闭的`CacheManager` 管理的 `Cache`的数据可能仍然可以被【其他】应用程序访问。
### 类加载
同一个 `CacheManager` 中的所有 `Cache` 共用用于创建 `CacheManager` 的类加载器。
如果不同的 `Cache` 要使用不同的类加载器,则必须通过创建不同的 `CacheManager` 实现。有关如何配置 `CacheManager` 的信息,请参阅关于 `CachingProvider` 的部分。
## `Cache`
开发者主要通过 `javax.cache.Cache` 与 `Cache` 进行交互。
`javax.cache.Cache` 接口提供了 Map-like 的方法来访问、更新、删除缓存条目。
`javax.cache.Cache` 接口定义如下:
```java
import javax.cache.configuration.CacheEntryListenerConfiguration;
import javax.cache.configuration.Configuration;
import javax.cache.event.CacheEntryListener;
import javax.cache.event.CacheEntryRemovedListener;
import javax.cache.expiry.ExpiryPolicy;
import javax.cache.integration.CacheLoader;
import javax.cache.integration.CacheWriter;
import javax.cache.integration.CompletionListener;
import javax.cache.processor.EntryProcessor;
import javax.cache.processor.EntryProcessorException;
import javax.cache.processor.EntryProcessorResult;
import java.io.Closeable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* A {@link Cache} is a Map-like data structure that provides temporary storage
* of application data.
*
* Like {@link Map}s, {@link Cache}s
*
* Unlike {@link Map}s, {@link Cache}s
*
* A simple example of how to use a cache is:
*
* If the cache is configured to use read-through, and get would return null
* because the entry is missing from the cache, the Cache's {@link CacheLoader}
* is called in an attempt to load the entry.
*
* @param key the key whose associated value is to be returned
* @return the element, or null, if it does not exist.
* @throws IllegalStateException if the cache is {@link #isClosed()}
* @throws NullPointerException if the key is null
* @throws CacheException if there is a problem fetching the value
* @throws ClassCastException if the implementation is configured to perform
* runtime-type-checking, and the key or value
* types are incompatible with those that have been
* configured for the {@link Cache}
*/
V get(K key);
/**
* Gets a collection of entries from the {@link Cache}, returning them as
* {@link Map} of the values associated with the set of keys requested.
*
* If the cache is configured read-through, and a get for a key would
* return null because an entry is missing from the cache, the Cache's
* {@link CacheLoader} is called in an attempt to load the entry. If an
* entry cannot be loaded for a given key, the key will not be present in
* the returned Map.
*
* @param keys The keys whose associated values are to be returned.
* @return A map of entries that were found for the given keys. Keys not found
* in the cache are not in the returned map.
* @throws NullPointerException if keys is null or if keys contains a null
* @throws IllegalStateException if the cache is {@link #isClosed()}
* @throws CacheException if there is a problem fetching the values
* @throws ClassCastException if the implementation is configured to perform
* runtime-type-checking, and the key or value
* types are incompatible with those that have been
* configured for the {@link Cache}
*/
Map
* More formally, returns true if and only if this cache contains a
* mapping for a key k such that key.equals(k).
* (There can be at most one such mapping.)
* If the cache is configured read-through the associated {@link CacheLoader}
* is not called. Only the cache is checked.
*
* If an entry for a key already exists in the Cache, a value will be loaded
* if and only if
* Implementations may choose to load multiple keys from the provided
* {@link Set} in parallel. Iteration however must not occur in parallel,
* thus allow for non-thread-safe {@link Set}s to be used.
*
* The thread on which the completion listener is called is implementation
* dependent. An implementation may also choose to serialize calls to
* different CompletionListeners rather than use a thread per
* CompletionListener.
*
* @param keys the keys to load
* @param replaceExistingValues when true existing values in the Cache will
* be replaced by those loaded from a CacheLoader
* @param completionListener the CompletionListener (may be null)
* @throws NullPointerException if keys is null or if keys contains a null.
* @throws IllegalStateException if the cache is {@link #isClosed()}
* @throws CacheException thrown if there is a problem performing the
* load. This may also be thrown on calling if
* there are insufficient threads available to
* perform the load.
* @throws ClassCastException if the implementation is configured to perform
* runtime-type-checking, and the key or value
* types are incompatible with those that have been
* configured for the {@link Cache}
*/
void loadAll(Set extends K> keys, boolean replaceExistingValues,
CompletionListener completionListener);
/**
* Associates the specified value with the specified key in the cache.
*
* If the {@link Cache} previously contained a mapping for the key, the old
* value is replaced by the specified value. (A cache c is said to
* contain a mapping for a key k if and only if {@link
* #containsKey(Object) c.containsKey(k)} would return true.)
*
* If the cache is configured write-through the
* {@link CacheWriter#write(Cache.Entry)} method will be called.
*
* If the cache previously contained a mapping for
* the key, the old value is replaced by the specified value. (A cache
* c is said to contain a mapping for a key k if and only
* if {@link #containsKey(Object) c.containsKey(k)} would return
* true.)
*
* The previous value is returned, or null if there was no value associated
* with the key previously.
* If the cache is configured write-through the associated
* {@link CacheWriter#write(Cache.Entry)} method will be called.
*
* The effect of this call is equivalent to that of calling
* {@link #put(Object, Object) put(k, v)} on this cache once for each mapping
* from key k to value v in the specified map.
*
* The order in which the individual puts occur is undefined.
*
* The behavior of this operation is undefined if entries in the cache
* corresponding to entries in the map are modified or removed while this
* operation is in progress. or if map is modified while the operation is in
* progress.
*
* In Default Consistency mode, individual puts occur atomically but not
* the entire putAll. Listeners may observe individual updates.
*
* If the cache is configured write-through the associated
* {@link CacheWriter#writeAll} method will be called.
*
* This is equivalent to:
*
* If the cache is configured write-through, and this method returns true,
* the associated {@link CacheWriter#write(Cache.Entry)} method will be called.
*
* More formally, if this cache contains a mapping from key k to
* value v such that
* Returns true if this cache previously associated the key,
* or false if the cache contained no mapping for the key.
*
* The cache will not contain a mapping for the specified key once the
* call returns.
*
* If the cache is configured write-through the associated
* {@link CacheWriter#delete(Object)} method will be called.
*
* This is equivalent to:
*
* If the cache is configured write-through, and this method returns true,
* the associated {@link CacheWriter#delete(Object)} method will be called.
*
* This is equivalent to:
*
* If the cache is configured write-through the associated
* {@link CacheWriter#delete(Object)} method will be called.
*
* This is equivalent to:
*
* If the cache is configured write-through, and this method returns true,
* the associated {@link CacheWriter#write(Cache.Entry)} method will be called.
*
* This is equivalent to
*
* If the cache is configured write-through, and this method returns true,
* the associated {@link CacheWriter#write(Cache.Entry)} method will be called.
*
* This is equivalent to
*
* If the cache is configured write-through, and this method returns true,
* the associated {@link CacheWriter#write(Cache.Entry)} method will be called.
*
* The order in which the individual entries are removed is undefined.
*
* For every entry in the key set, the following are called:
*
* The order that the individual entries are removed is undefined.
*
* For every mapping that exists the following are called:
*
* This is potentially an expensive operation as listeners are invoked.
* Use {@link #clear()} to avoid this.
*
* @throws IllegalStateException if the cache is {@link #isClosed()}
* @throws CacheException if there is a problem during the remove
* @see #clear()
* @see CacheWriter#deleteAll
*/
void removeAll();
/**
* Clears the contents of the cache, without notifying listeners or
* {@link CacheWriter}s.
*
* @throws IllegalStateException if the cache is {@link #isClosed()}
* @throws CacheException if there is a problem during the clear
*/
void clear();
/**
* Provides a standard way to access the configuration of a cache using
* JCache configuration or additional proprietary configuration.
*
* The returned value must be immutable.
*
* If the provider's implementation does not support the specified class,
* the {@link IllegalArgumentException} is thrown.
*
* @param
* The order that the entries for the keys are processed is undefined.
* Implementations may choose to process the entries in any order, including
* concurrently. Furthermore there is no guarantee implementations will
* use the same {@link EntryProcessor} instance to process each entry, as
* the case may be in a non-local cache topology.
*
* The result of executing the {@link EntryProcessor} is returned as a
* {@link Map} of {@link EntryProcessorResult}s, one result per key. Should the
* {@link EntryProcessor} or Caching implementation throw an exception, the
* exception is wrapped and re-thrown when a call to
* {@link javax.cache.processor.EntryProcessorResult#get()} is made.
*
* @param
* Closing a Cache does not necessarily destroy the contents of a Cache.
* It simply signals to the owning CacheManager that the Cache is no longer
* required by the application and that future uses of a specific Cache instance
* should not be permitted.
*
* Depending on the implementation and Cache topology,
* (e.g. a storage-backed or distributed cache), the contents of a closed Cache
* may still be available and accessible by other applications, or, in fact, via
* the Cache Manager that previously owned the Cache, if an application calls
* getCache at some point in the future.
*
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
void close();
/**
* Determines whether this Cache instance has been closed. A Cache is
* considered closed if;
*
* This method generally cannot be called to determine whether a Cache instance
* is valid or invalid. A typical client can determine that a Cache is invalid
* by catching any exceptions that might be thrown when an operation is
* attempted.
*
* @return true if this Cache instance is closed; false if it is still open
*/
boolean isClosed();
/**
* Provides a standard way to access the underlying concrete caching
* implementation to provide access to further, proprietary features.
*
* If the provider's implementation does not support the specified class,
* the {@link IllegalArgumentException} is thrown.
*
* @param
* Both listeners registered at configuration time,
* and those created at runtime with {@link #registerCacheEntryListener} can
* be deregistered.
*
* @param cacheEntryListenerConfiguration
* the factory and related configuration
* that was used to create the
* listener
* @throws IllegalStateException if the cache is {@link #isClosed()}
*/
void deregisterCacheEntryListener(CacheEntryListenerConfiguration
* The ordering of iteration over entries is undefined.
*
* During iteration, any entries that are removed will have their appropriate
* CacheEntryRemovedListeners notified.
*
* When iterating over a cache it must be assumed that the underlying
* cache may be changing, with entries being added, removed, evicted
* and expiring. {@link java.util.Iterator#next()} may therefore return
* null.
*
* @throws IllegalStateException if the cache is {@link #isClosed()}
*/
Iterator
* If the provider's implementation does not support the specified class,
* the {@link IllegalArgumentException} is thrown.
*
* @param
* Each of the functions return a new {@link Duration} that specifies the
* amount of time that must pass before a cache entry is considered expired.
* {@link Duration} has constants defined for useful durations.
*
* @author Brian Oliver
* @author Greg Luck
* @since 1.0
* @see Duration
*/
public interface ExpiryPolicy {
/**
* Gets the {@link Duration} before a newly created Cache.Entry is considered
* expired.
*
* This method is called by a caching implementation after a Cache.Entry is
* created, but before a Cache.Entry is added to a cache, to determine the
* {@link Duration} before an entry expires. If a {@link Duration#ZERO}
* is returned the new Cache.Entry is considered to be already expired and
* will not be added to the Cache.
*
* Should an exception occur while determining the Duration, an implementation
* specific default {@link Duration} will be used.
*
* @return the new {@link Duration} before a created entry expires
*/
Duration getExpiryForCreation();
/**
* Gets the {@link Duration} before an accessed Cache.Entry is
* considered expired.
*
* This method is called by a caching implementation after a Cache.Entry is
* accessed to determine the {@link Duration} before an entry expires. If a
* {@link Duration#ZERO} is returned a Cache.Entry will be
* considered immediately expired. Returning
* Should an exception occur while determining the Duration, an implementation
* specific default Duration will be used.
*
* @return the new {@link Duration} before an accessed entry expires
*/
Duration getExpiryForAccess();
/**
* Gets the {@link Duration} before an updated Cache.Entry is considered
* expired.
*
* This method is called by the caching implementation after a Cache.Entry is
* updated to determine the {@link Duration} before the updated entry expires.
* If a {@link Duration#ZERO} is returned a Cache.Entry is considered
* immediately expired. Returning
* Should an exception occur while determining the Duration, an implementation
* specific default Duration will be used.
*
* @return the new {@link Duration} before an updated entry expires
*/
Duration getExpiryForUpdate();
}
```
缓存条目在执行完指定操作一段时间后过期,这个时间间隔由 `javax.cache.expiry.Duration` 来定义。 `Duration` 由 `java.util.concurrent.TimeUnit` 和 `long durationAmount` 两部分组成,最小的时间单位是 `TimeUnit.MILLISECONDS`;
过期时间由配置的过期策略和执行的缓存操作有关。下面是 `ExpiryPolicy` 接口中对于指定操作获取对应的时间间隔的方法
- `getExpiryForCreation()` 条目创建时的有效时长
- `getExpiryForAccess()` 条目被访问时新的有效时长
- `getExpiryForUpdate()` 条目更新时新的有效时长
当一个缓存实现调用了上面的三个方法,会返回下面几种结果其中之一:
- 一个新的有效时长
- `Duration.ZERO`,代表条目立即过期
- `null`,`getExpiryForUpdate()` 和 `getExpiryForAccess()` 可能返回,代表不修改条目当前的有效时长。
除了 `Duration#ZERO`,还定义了如下常量
```java
/**
* ETERNAL (forever).
*/
public static final Duration ETERNAL = new Duration();
/**
* One day.
*/
public static final Duration ONE_DAY = new Duration(DAYS, 1);
/**
* One hour.
*/
public static final Duration ONE_HOUR = new Duration(HOURS, 1);
/**
* Thirty minutes.
*/
public static final Duration THIRTY_MINUTES = new Duration(MINUTES, 30);
/**
* Twenty minutes.
*/
public static final Duration TWENTY_MINUTES = new Duration(MINUTES, 20);
/**
* Ten minutes.
*/
public static final Duration TEN_MINUTES = new Duration(MINUTES, 10);
/**
* Five minutes.
*/
public static final Duration FIVE_MINUTES = new Duration(MINUTES, 5);
/**
* One minute.
*/
public static final Duration ONE_MINUTE = new Duration(MINUTES, 1);
/**
* Zero (no time).
*/
public static final Duration ZERO = new Duration(SECONDS, 0);
```
下面的表格中描述了缓存方法如何与过期策略进行交互
|缓存方法|`ExpiryPolicy.getExpiryForCreation`
* Under Default Consistency, the non-batch writer methods are atomic with respect
* to the corresponding cache operation.
*
* For batch methods under Default Consistency, the entire cache operation
* is not required to be atomic in {@link Cache} and is therefore not required to
* be atomic in the writer. As individual writer operations can fail, cache
* operations are not required to occur until after the writer batch method has
* returned or, in the case of partial success, thrown an exception. In the case
* of partial success, the collection of entries return must only contain
* those entries that failed.
*
* The entry passed into {@link #write(Cache.Entry)} is independent
* of the cache mapping for that key, meaning that if the value changes in the
* cache or is removed it does not change the entry.
*
* @param
* This method is intended to support both key/value creation and value update
* for a specific key.
*
* @param entry the entry to be written
* @throws CacheWriterException if the write fails. If thrown the
* cache mutation will not occur.
*/
void write(Cache.Entry extends K, ? extends V> entry) throws CacheWriterException;
/**
* Write the specified entries to the external resource. This method is intended
* to support both insert and update.
*
* The order that individual writes occur is undefined, as
* {@link Cache#putAll(java.util.Map)} also has undefined ordering.
*
* If this operation fails (by throwing an exception) after a partial success,
* the writer must remove any successfully written entries from the entries
* collection so that the caching implementation knows what succeeded and can
* mutate the cache.
*
* @param entries a mutable collection to write. Upon invocation, it contains
* the entries to write for write-through. Upon return the
* collection must only contain entries that were not
* successfully written. (see partial success above)
* @throws CacheWriterException if one or more of the writes fail. If
* thrown cache mutations will occur for
* entries that succeeded.
*/
void writeAll(Collection
* Expiry of a cache entry is not a delete hence will not cause this method to
* be invoked.
*
* This method is invoked even if no mapping for the key exists.
*
* @param key the key that is used for the delete operation
* @throws CacheWriterException if delete fails. If thrown the cache delete will
* not occur.
*/
void delete(Object key) throws CacheWriterException;
/**
* Remove data and keys from the external resource for the given collection of
* keys, if present.
*
* The order that individual deletes occur is undefined, as
* {@link Cache#removeAll(java.util.Set)} also has undefined ordering.
*
* If this operation fails (by throwing an exception) after a partial success,
* the writer must remove any successfully written entries from the entries
* collection so that the caching implementation knows what succeeded and can
* mutate the cache.
*
* Expiry of a cache entry is not a delete hence will not cause this method to
* be invoked.
*
* This method may include keys even if there is no mapping for that key,
* in which case the data represented by that key should be removed from the
* underlying resource.
*
* @param keys a mutable collection of keys for entries to delete. Upon
* invocation, it contains the keys to delete for write-through.
* Upon return the collection must only contain the keys that were
* not successfully deleted. (see partial success above)
* @throws CacheWriterException if one or more deletes fail. If thrown
* cache deletes will occur for entries that
* succeeded.
*/
void deleteAll(Collection> keys) throws CacheWriterException;
}
```
### 缓存加载
`loadAll` 方法用来将外部资源加载到缓存中,定义如下:
```java
/**
* Asynchronously loads the specified entries into the cache using the
* configured {@link CacheLoader} for the given keys.
*
* If an entry for a key already exists in the Cache, a value will be loaded
* if and only if
* Implementations may choose to load multiple keys from the provided
* {@link Set} in parallel. Iteration however must not occur in parallel,
* thus allow for non-thread-safe {@link Set}s to be used.
*
* The thread on which the completion listener is called is implementation
* dependent. An implementation may also choose to serialize calls to
* different CompletionListeners rather than use a thread per
* CompletionListener.
*
* @param keys the keys to load
* @param replaceExistingValues when true existing values in the Cache will
* be replaced by those loaded from a CacheLoader
* @param completionListener the CompletionListener (may be null)
* @throws NullPointerException if keys is null or if keys contains a null.
* @throws IllegalStateException if the cache is {@link #isClosed()}
* @throws CacheException thrown if there is a problem performing the
* load. This may also be thrown on calling if
* there are insufficient threads available to
* perform the load.
* @throws ClassCastException if the implementation is configured to perform
* runtime-type-checking, and the key or value
* types are incompatible with those that have been
* configured for the {@link Cache}
*/
void loadAll(Set extends K> keys, boolean replaceExistingValues,
CompletionListener completionListener);
```
为了使用这个方法,在创建缓存时必须配置 `CacheLoader`。不需要将缓存配置为 `read-through` 模式。
加载可能耗时较长,因为这个原因,可以给该方法传递一个 `CompletionListener`,来接收加载完成或加载异常的通知。该接口的定义如下:
```java
package javax.cache.integration;
/**
* A CompletionListener is implemented by an application when it needs to be
* notified of the completion of some Cache operation.
*
* When the operation is complete, the Cache provider notifies the application
* by calling the {@link #onCompletion()} method of the {@link
* CompletionListener}.
*
* If the operation fails for any reason, the Cache provider calls the
* {@link #onException(Exception)} method of the {@link CompletionListener}.
*
* To support a Java Future-based approach to synchronously wait for a Cache
* operation to complete, use a {@link CompletionListenerFuture}.
*
* A Cache provider will use an implementation specific thread to call methods
* on this interface.
*
* @author Brian Oliver
* @since 1.0
* @see CompletionListenerFuture
*/
public interface CompletionListener {
/**
* Notifies the application that the operation completed successfully.
*/
void onCompletion();
/**
* Notifies the application that the operation failed.
*
* @param e the Exception that occurred
*/
void onException(Exception e);
}
```
本规范也提供了一个阻塞版本的 `CompletionListener` 实现,`CompletionListenerFuture`。它实现了 `CompletionListener` 和 `Future` 两个接口。如果 `onException(Exception e)` 方法被调用,异常会被重新封装成 `ExecutionException` 由 `Future get()/get(long timeout, TimeUnit unit)` 重抛。
#### 例子
```java
HashSet
* The value will be available
* for {@link CacheEntryCreatedListener} and {@link CacheEntryUpdatedListener}.
* Returns the same value as {@link #getOldValue()} for
* {@link CacheEntryExpiredListener} and {@link CacheEntryRemovedListener}.
* Cache clients that need to maintain compatibility with JSR107 version 1.0
* cache implementations, need to use this method for retrieving the expired
* or removed value. When using cache implementations compatible with JSR107
* version 1.1, clients should prefer the method {@link #getOldValue()}.
*
* @return the value corresponding to this entry
* @see #getOldValue()
*/
@Override
public abstract V getValue();
/**
* Returns the previous value that existed for entry in the cache before
* modification or removal.
*
* The old value will be available
* for {@link CacheEntryUpdatedListener}, {@link CacheEntryExpiredListener}
* and {@link CacheEntryRemovedListener}
* if {@link CacheEntryListenerConfiguration#isOldValueRequired()} is true.
* The old value may be available for {@link CacheEntryUpdatedListener},
* {@link CacheEntryExpiredListener} and {@link CacheEntryRemovedListener}
* if {@link CacheEntryListenerConfiguration#isOldValueRequired()} is false.
*
* @return the previous value or
* Sub-interfaces exist for the various cache events allowing a listener to be
* created that implements only those listeners it is interested in.
*
* Listeners should be implemented with care. In particular it is important to
* consider their impact on performance and latency.
*
* Listeners:
*
* Listeners can only throw {@link CacheEntryListenerException}. Caching
* implementations must catch any other {@link Exception} from a listener, then
* wrap and rethrow it as a {@link CacheEntryListenerException}.
*
* A listener that mutates a cache on the CacheManager may cause a deadlock.
* Detection and response to deadlocks is implementation specific.
*
* @param
* If an entry for the key existed prior to the operation it is not invoked,
* instead {@link CacheEntryUpdatedListener} is invoked.
*
* @param
* When
* A filter must not create side effects.
*
* @param
* Mutable entries are used by {@link EntryProcessor}s to mutate
* {@link Cache.Entry}s in place, atomically.
*
* @param
* This has the same semantics as calling {@link Cache#remove}.
*/
void remove();
/**
* Returns the value stored in the cache.
*
* If the cache is configured to use read-through, and this method
* would return null because the entry is missing from the cache,
* the Cache's {@link CacheLoader} is called in an attempt to load
* the entry.
*
* @return the value corresponding to this entry
*/
V getValue();
/**
* Sets or replaces the value associated with the key.
*
* If {@link #exists} is false and setValue is called
* then a mapping is added to the cache visible once the EntryProcessor
* completes. Moreover a second invocation of {@link #exists()}
* will return true.
*
* @param value the value to update the entry with
* @throws ClassCastException if the implementation supports and is
* configured to perform runtime-type-checking,
* and value type is incompatible with that
* which has been configured for the
* {@link Cache}
*/
void setValue(V value);
}
```
应用可能想要原子的检查条目的值,计算新值,更新条目并返回其他值,可以考虑使用 `EntryProcessor` 来实现这个操作。
`javax.cache.processor.EntryProcessor` 接口定义如下:
```java
package javax.cache.processor;
import javax.cache.Cache;
import javax.cache.event.CacheEntryListener;
import javax.cache.expiry.ExpiryPolicy;
import javax.cache.integration.CacheWriter;
/**
* An invocable function that allows applications to perform compound operations
* on a {@link javax.cache.Cache.Entry} atomically, according to the defined
* consistency of a {@link Cache}.
*
* Any {@link javax.cache.Cache.Entry} mutations will not take effect until after
* the {@link EntryProcessor#process(MutableEntry, Object...)} method has completed
* execution.
*
* If an exception is thrown by an {@link EntryProcessor}, a Caching Implementation
* must wrap any {@link Exception} thrown wrapped in an {@link
* EntryProcessorException}. If this occurs no mutations will be made to the
* {@link javax.cache.Cache.Entry}.
*
* Implementations may execute {@link EntryProcessor}s in situ, thus avoiding
* locking, round-trips and expensive network transfers.
*
*
* {@link javax.cache.Cache.Entry} mutation, via a call to
* {@link MutableEntry#setValue(Object)}, will behave as if {@link
* Cache#put(Object, Object)} was called for the key. This includes updating
* necessary statistics, consulting the configured {@link
* ExpiryPolicy}, notifying {@link CacheEntryListener}s and writing to a
* configured {@link CacheWriter}.
*
* {@link javax.cache.Cache.Entry} removal, via a call to
* {@link MutableEntry#remove()}, will behave as if {@link Cache#remove(Object)}
* was called for the key. This includes updating necessary statistics, notifying
* {@link CacheEntryListener}s and causing a delete on a configured
* {@link CacheWriter}.
*
* As implementations may choose to execute {@link EntryProcessor}s remotely,
* {@link EntryProcessor}s, together with specified parameters and return
* values, may be required to implement {@link java.io.Serializable}.
*
*
* The order that the entries for the keys are processed is undefined.
* Implementations may choose to process the entries in any order, including
* concurrently. Furthermore there is no guarantee implementations will
* use the same {@link EntryProcessor} instance to process each entry, as
* the case may be in a non-local cache topology.
*
* The result of executing the {@link EntryProcessor} is returned as a
* {@link Map} of {@link EntryProcessorResult}s, one result per key. Should the
* {@link EntryProcessor} or Caching implementation throw an exception, the
* exception is wrapped and re-thrown when a call to
* {@link javax.cache.processor.EntryProcessorResult#get()} is made.
*
* @param
* The meaning and semantics of the {@link URI} used to identify a
* {@link CacheManager} is implementation dependent. For applications to remain
* implementation independent, they should avoid attempting to create {@link URI}s
* and instead use those returned by {@link #getDefaultURI()}.
*
* @author Brian Oliver
* @author Greg Luck
* @since 1.0
*/
public interface CachingProvider extends Closeable {
/**
* Requests a {@link CacheManager} configured according to the implementation
* specific {@link URI} be made available that uses the provided
* {@link ClassLoader} for loading underlying classes.
*
* Multiple calls to this method with the same {@link URI} and
* {@link ClassLoader} must return the same {@link CacheManager} instance,
* except if a previously returned {@link CacheManager} has been closed.
*
* Properties are used in construction of a {@link CacheManager} and do not form
* part of the identity of the CacheManager. i.e. if a second call is made to
* with the same {@link URI} and {@link ClassLoader} but different properties,
* the {@link CacheManager} created in the first call is returned.
*
* Properties names follow the same scheme as package names.
* The prefixes {@code java} and {@code javax} are reserved.
* Properties are passed through and can be retrieved via
* {@link CacheManager#getProperties()}.
* Properties within the package scope of a caching implementation may be used for
* additional configuration.
*
* @param uri an implementation specific URI for the
* {@link CacheManager} (null means use
* {@link #getDefaultURI()})
* @param classLoader the {@link ClassLoader} to use for the
* {@link CacheManager} (null means use
* {@link #getDefaultClassLoader()})
* @param properties the {@link Properties} for the {@link CachingProvider}
* to create the {@link CacheManager} (null means no
* implementation specific Properties are required)
* @throws CacheException when a {@link CacheManager} for the
* specified arguments could not be produced
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
CacheManager getCacheManager(URI uri, ClassLoader classLoader,
Properties properties);
/**
* Obtains the default {@link ClassLoader} that will be used by the
* {@link CachingProvider}.
*
* @return the default {@link ClassLoader} used by the {@link CachingProvider}
*/
ClassLoader getDefaultClassLoader();
/**
* Obtains the default {@link URI} for the {@link CachingProvider}.
*
* Use this method to obtain a suitable {@link URI} for the
* {@link CachingProvider}.
*
* @return the default {@link URI} for the {@link CachingProvider}
*/
URI getDefaultURI();
/**
* Obtains the default {@link Properties} for the {@link CachingProvider}.
*
* Use this method to obtain suitable {@link Properties} for the
* {@link CachingProvider}.
*
* @return the default {@link Properties} for the {@link CachingProvider}
*/
Properties getDefaultProperties();
/**
* Requests a {@link CacheManager} configured according to the implementation
* specific {@link URI} that uses the provided {@link ClassLoader} for loading
* underlying classes.
*
* Multiple calls to this method with the same {@link URI} and
* {@link ClassLoader} must return the same {@link CacheManager} instance,
* except if a previously returned {@link CacheManager} has been closed.
*
* @param uri an implementation specific {@link URI} for the
* {@link CacheManager} (null means
* use {@link #getDefaultURI()})
* @param classLoader the {@link ClassLoader} to use for the
* {@link CacheManager} (null means
* use {@link #getDefaultClassLoader()})
* @throws CacheException when a {@link CacheManager} for the
* specified arguments could not be produced
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
CacheManager getCacheManager(URI uri, ClassLoader classLoader);
/**
* Requests a {@link CacheManager} configured according to the
* {@link #getDefaultURI()} and {@link #getDefaultProperties()} be made
* available that using the {@link #getDefaultClassLoader()} for loading
* underlying classes.
*
* Multiple calls to this method must return the same {@link CacheManager}
* instance, except if a previously returned {@link CacheManager} has been
* closed.
*
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
CacheManager getCacheManager();
/**
* Closes all of the {@link CacheManager} instances and associated resources
* created and maintained by the {@link CachingProvider} across all
* {@link ClassLoader}s.
*
* After closing the {@link CachingProvider} will still be operational. It
* may still be used for acquiring {@link CacheManager} instances, though
* those will now be new.
*
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
void close();
/**
* Closes all {@link CacheManager} instances and associated resources created
* by the {@link CachingProvider} using the specified {@link ClassLoader}.
*
* After closing the {@link CachingProvider} will still be operational. It
* may still be used for acquiring {@link CacheManager} instances, though
* those will now be new for the specified {@link ClassLoader} .
*
* @param classLoader the {@link ClassLoader} to release
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
void close(ClassLoader classLoader);
/**
* Closes all {@link CacheManager} instances and associated resources created
* by the {@link CachingProvider} for the specified {@link URI} and
* {@link ClassLoader}.
*
* @param uri the {@link URI} to release
* @param classLoader the {@link ClassLoader} to release
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
void close(URI uri, ClassLoader classLoader);
/**
* Determines whether an optional feature is supported by the
* {@link CachingProvider}.
*
* @param optionalFeature the feature to check for
* @return true if the feature is supported
*/
boolean isSupported(OptionalFeature optionalFeature);
}
```
尽管是可选的,在 Java SE 环境中获取 `CachingProvider` 的主要途径是 `Caching` 类。
`Caching` 类提供了三种方式来加载和实例化 `CachingProvider`。
- 假设将实现定义为服务,并通过使用 `java.util.ServiceLoader` 对其进行解析
- 许开发人员使用 `javax.cache.CachingProvider` 对应的Java系统属性来指定默认实现的全类名。
- 允许应用程序使用所需的 `CachingProvider` 的全类名来显式请求特定的实现
尽管开发人员可以选择使用依赖于实现的方式来获取 `CachingProvider`,但这样做可能会降低可移植性。
为了使 `CachingProvider` 实现由 `Caching` 类通过 `java.util.ServiceLoader` 自动定位,必须以 Jar 文件规范中定义的格式,在 `META-INF/services/javax.cache.spi.CachingProvider` 中定义`CachingProvider` 实现的全类名。
`javax.cache.spi.CachingProvider` 配置文件用于为 `Caching` 类定义特定的 `CachingProvider` 实现类,从而允许它根据请求自动定位,加载并提供适当的实例给应用程序。
`javax.cache.spi.CachingProvider` 配置文件的内容只是一个或多个全类名,每个类名都位于单独的行中,每个类名都是可用的`CachingProvider` 实现。
例如:
Java Caching API 实现程序 ACME Caching Products 附带了一个名为 acme.jar 的 JAR,其中包含 `CachingProvider` 实现。 JAR的内容包括 `CachingProvider` 实现和 `javax.cache.spi.CachingProvider` 配置文件。
```
META-INF/services/javax.cache.spi.CachingProvider
com/acme/cache/ACMECachingProvider.class
...
```
`META-INF/services/javax.cache.spi.CachingProvider` 的内容只不过是实现类的名称:`com.acme.cache.ACMECachingProvider`
通过正确配置 `META-INF/services/javax.cache.spi.CachingProvider` 文件,应用程序可以使用多个 `CachingProvider` 实现。 当有多个 `CachingProvider` 可用时,从 `Caching` 类返回默认 `CachingProvider` 的请求将导致异常。
`Caching` 类定义如下:
```java
package javax.cache;
import javax.cache.spi.CachingProvider;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.ServiceLoader;
import java.util.WeakHashMap;
/**
* The {@link Caching} class provides a convenient means for an application to
* acquire an appropriate {@link CachingProvider} implementation.
*
* While defined as part of the specification, its use is not required.
* Applications and/or containers may instead choose to directly instantiate a
* {@link CachingProvider} implementation based on implementation specific
* instructions.
*
* When using the {@link Caching} class, {@link CachingProvider} implementations
* are automatically discovered when they follow the conventions outlined by the
* Java Development Kit {@link ServiceLoader} class.
*
* Although automatically discovered, applications that choose to use this class
* should not make assumptions regarding the order in which implementations are
* returned by the {@link #getCachingProviders()} or
* {@link #getCachingProviders(ClassLoader)} methods.
*
* For a {@link CachingProvider} to be automatically discoverable by the
* {@link Caching} class, the fully qualified class name of the
* {@link CachingProvider} implementation must be declared in the following
* file:
*
* For example, in the reference implementation the contents of this file are:
*
* Alternatively when the fully qualified class name of a
* {@link CachingProvider} implementation is specified using the system property
*
* All {@link CachingProvider}s that are automatically detected or explicitly
* declared and loaded by the {@link Caching} class are maintained in an
* internal registry. Consequently when a previously loaded
* {@link CachingProvider} is requested, it will be simply returned from the
* internal registry, without reloading and/or instantiating the said
* implementation again.
*
* As required by some applications and containers, multiple co-existing
* {@link CachingProvider}s implementations, from the same or different
* implementors are permitted at runtime.
*
* To iterate through those that are currently registered a developer may use
* the following methods:
*
* Where multiple {@link CachingProvider}s are present, the
* {@link CachingProvider} returned by getters {@link #getCachingProvider()} and
* {@link #getCachingProvider(ClassLoader)} is undefined and as a result a
* {@link CacheException} will be thrown when attempted.
*
* @author Brian Oliver
* @author Greg Luck
* @author Yannis Cosmadopoulos
* @since 1.0
* @see ServiceLoader
* @see CachingProvider
*/
public final class Caching {
/**
* The
* By default this is the {@link Thread#getContextClassLoader()}.
*
* @return the default {@link ClassLoader}
*/
public static ClassLoader getDefaultClassLoader() {
return CACHING_PROVIDERS.getDefaultClassLoader();
}
/**
* Set the {@link ClassLoader} to use for API methods that don't explicitly
* require a {@link ClassLoader}, but internally use one.
*
* @param classLoader the {@link ClassLoader} or
* If a
* If a
* This method must be used for {@link Cache}s that were configured with
* runtime key and value types. Use {@link CacheManager#getCache(String)} for
* {@link Cache}s where these were not specified.
*
* Implementations must ensure that the key and value types are the same as
* those configured for the {@link Cache} prior to returning from this method.
*
* Implementations may further perform type checking on mutative cache operations
* and throw a {@link ClassCastException} if these checks fail.
*
* Implementations that support declarative mechanisms for pre-configuring
* {@link Cache}s may return a pre-configured {@link Cache} instead of
* null.
*
* @param null.
*
* @param
*
* followed by allowing the name of the {@link Cache} to be used for other
* {@link Cache} configurations.
* javax.cache:type=CacheConfiguration
*
*
*
* @param cacheName the name of the cache to register
* @param enabled true to enable management, false to disable.
* @throws IllegalStateException if the {@link CacheManager} or
* {@link Cache} {@link #isClosed()}
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
void enableManagement(String cacheName, boolean enabled);
/**
* Enables or disables statistics gathering for a managed {@link Cache} at
* runtime.
* javax.cache:type=CacheStatistics
*
*
*
* @param cacheName the name of the cache to register
* @param enabled true to enable statistics, false to disable.
* @throws IllegalStateException if the {@link CacheManager} or
* {@link Cache} {@link #isClosed()}
* @throws NullPointerException if cacheName is null
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
void enableStatistics(String cacheName, boolean enabled);
/**
* Closes the {@link CacheManager}.
* true.
*
*
* Object.class if the type is undefined
*/
ClassObject.class if the type is undefined
*/
Class
*
* Storage by reference only applies to the local heap. If an entry is moved off
* heap it will need to be transformed into a representation. Any mutations that
* occur after transformation may not be reflected in the cache.
* true.
*
* @return true if the cache is store by value
*/
boolean isStoreByValue();
}
```
`javax.cache.configuration.CompleteConfiguration` 接口定义如下:
```java
package javax.cache.configuration;
import javax.cache.expiry.ExpiryPolicy;
import javax.cache.integration.CacheLoader;
import javax.cache.integration.CacheWriter;
import java.io.Serializable;
/**
* A read-only representation of the complete JCache {@link javax.cache.Cache}
* configuration.
* false.
*
* @return true when a {@link javax.cache.Cache} is in
* "read-through" mode.
* @see #getCacheLoaderFactory()
*/
boolean isReadThrough();
/**
* Determines if a {@link javax.cache.Cache} should operate in write-through
* mode.
* false.
*
* @return true when a {@link javax.cache.Cache} is in
* "write-through" mode.
* @see #getCacheWriterFactory()
*/
boolean isWriteThrough();
/**
* Checks whether statistics collection is enabled in this cache.
* false.
*
* @return true if statistics collection is enabled
*/
boolean isStatisticsEnabled();
/**
* Checks whether management is enabled on this cache.
* false.
*
* @return true if management is enabled
*/
boolean isManagementEnabled();
/**
* Obtains the {@link javax.cache.configuration.CacheEntryListenerConfiguration}s
* for {@link javax.cache.event.CacheEntryListener}s to be configured on a
* {@link javax.cache.Cache}.
*
* @return an {@link Iterable} over the
* {@link javax.cache.configuration.CacheEntryListenerConfiguration}s
*/
Iterablenull.
*
* @return the {@link javax.cache.configuration.Factory} for the
* {@link javax.cache.integration.CacheLoader} or null if none has been set.
*/
Factorynull.
*
* @return the {@link javax.cache.configuration.Factory} for the
* {@link javax.cache.integration.CacheWriter} or null if none has been set.
*/
Factorynull)
*/
Factory{@code
* CacheConfiguration
* @see #setTypes(Class, Class)
*/
public MutableConfiguration()
/**
* Constructs a {@link MutableConfiguration} based on another
* {@link CompleteConfiguration}.
*
* @param configuration the {@link CompleteConfiguration}
*/
public MutableConfiguration(CompleteConfigurationObject.class means type-safety checks are not required.
* null
* is specified the default {@link ExpiryPolicy} is used.
* true if read-through is required
* @return the {@link MutableConfiguration} to permit fluent-style method calls
*/
public MutableConfigurationtrue if write-through is required
* @return the {@link MutableConfiguration} to permit fluent-style method calls
*/
public MutableConfigurationtrue if store-by-value is required,
* false for store-by-reference
* @return the {@link MutableConfiguration} to permit fluent-style method calls
*/
public MutableConfiguration
*
* followed by allowing the name of the {@link Cache} to be used for other
* {@link Cache} configurations.
*
*
*
*
* null
* will result in a {@link NullPointerException}
*
* @param
* String cacheName = "sampleCache";
* CachingProvider provider = Caching.getCachingProvider();
* CacheManager manager = provider.getCacheManager();
* Cache<Integer, Date> cache = manager.getCache(cacheName, Integer.class,
* Date.class);
* Date value1 = new Date();
* Integer key = 1;
* cache.put(key, value1);
* Date value2 = cache.get(key);
* replaceExistingValues is true. If no loader
* is configured for the cache, no objects will be loaded. If a problem is
* encountered during the retrieving or loading of the objects,
* an exception is provided to the {@link CompletionListener}. Once the
* operation has completed, the specified CompletionListener is notified.
*
* except that the action is performed atomically.
*
* if (!cache.containsKey(key)) {}
* cache.put(key, value);
* return true;
* } else {
* return false;
* }
* (key==null ? k==null : key.equals(k)), that mapping is removed.
* (The cache can contain at most one such mapping.)
*
*
* except that the action is performed atomically.
*
* if (cache.containsKey(key) && equals(cache.get(key), oldValue) {
* cache.remove(key);
* return true;
* } else {
* return false;
* }
*
* except that the action is performed atomically.
*
* if (cache.containsKey(key)) {
* V oldValue = cache.get(key);
* cache.remove(key);
* return oldValue;
* } else {
* return null;
* }
*
* except that the action is performed atomically.
*
* if (cache.containsKey(key) && equals(cache.get(key), oldValue)) {
* cache.put(key, newValue);
* return true;
* } else {
* return false;
* }
*
* except that the action is performed atomically.
*
* if (cache.containsKey(key)) {
* cache.put(key, value);
* return true;
* } else {
* return false;
* }
* except that the action is performed atomically.
*
* if (cache.containsKey(key)) {
* V oldValue = cache.get(key);
* cache.put(key, value);
* return oldValue;
* } else {
* return null;
* }
*
*
*
* @param keys the keys to remove
* @throws NullPointerException if keys is null or if it contains a null key
* @throws IllegalStateException if the cache is {@link #isClosed()}
* @throws CacheException if there is a problem during the remove
* @throws ClassCastException if the implementation is configured to perform
* runtime-type-checking, and the key or value
* types are incompatible with those that have been
* configured for the {@link Cache}
* @see CacheWriter#deleteAll
*/
void removeAll(Set extends K> keys);
/**
* Removes all of the mappings from this cache.
*
*
* If the cache is empty, the {@link CacheWriter} is not called.
* null value for a key.
* @throws NullPointerException if keys or {@link EntryProcessor} are null
* @throws IllegalStateException if the cache is {@link #isClosed()}
* @throws ClassCastException if the implementation is configured to perform
* runtime-type-checking, and the key or value
* types are incompatible with those that have been
* configured for the {@link Cache}
* @see EntryProcessor
*/
null if the {@link Cache} is not
* managed
*/
CacheManager getCacheManager();
/**
* Closing a {@link Cache} signals to the {@link CacheManager} that produced or
* owns the {@link Cache} that it should no longer be managed. At this
* point in time the {@link CacheManager}:
*
*
* Once closed any attempt to use an operational method on a Cache will throw an
* {@link IllegalStateException}.
* close
* method on configured {@link CacheLoader},
* {@link CacheWriter}, registered {@link CacheEntryListener}s and
* {@link ExpiryPolicy} instances that implement the java.io.Closeable
* interface.
*
*
* Object.class means type-safety checks are not required.
*
* This is used by {@link CacheManager} to ensure that the key and value
* types are the same as those configured for the {@link Cache} prior to
* returning a requested cache from this method.
*
* Implementations may further perform type checking on mutative cache operations
* and throw a {@link ClassCastException} if these checks fail.
*
* @param keyType the expected key type
* @param valueType the expected value type
* @return the {@link MutableConfiguration} to permit fluent-style method calls
* @throws NullPointerException should the key or value type be null
* @see CacheManager#getCache(String, Class, Class)
*/
public MutableConfigurationnull will result
* in no change to the previously understood expiry {@link Duration}.
* null will result in no change
* to the previously understood expiry {@link Duration}.
*
是否调用|`ExpiryPolicy.getExpiryForAccess`
是否调用|`ExpiryPolicy.getExpiryForUpdate`
是否调用|
|---|---|---|---|
|`boolean containsKey(K key)`|NO|NO|NO|
|`V get(K key)`|NO (unless read-though caused a load)|YES|NO|
|`Map
(1) setValue called and entry did not exist for key before invoke was called.
(2) if read-through enabled and getValue() is called and causes a new entry to be loaded for key)|Yes (when getValue was called and no other mutations occurred during entry processor execution. note: Create, modify or remove take precedence over Access)|Yes (when setValue was called and the entry already existed before entry processor was called)|
|`null should be returned.
*
* @param key the key identifying the object being loaded
* @return The value for the entry that is to be stored in the cache or
* null if the object can't be loaded
* @throws CacheLoaderException if there is problem executing the loader.
*/
V load(K key) throws CacheLoaderException;
/**
* Loads multiple objects. Application developers should implement this
* method to customize the loading of cache entries. This method is called
* when the requested object is not in the cache. If an object can't be loaded,
* it is not returned in the resulting map.
*
* @param keys keys identifying the values to be loaded
* @return A map of key, values to be stored in the cache.
* @throws CacheLoaderException if there is problem executing the loader.
*/
MapreplaceExistingValues is true. If no loader
* is configured for the cache, no objects will be loaded. If a problem is
* encountered during the retrieving or loading of the objects,
* an exception is provided to the {@link CompletionListener}. Once the
* operation has completed, the specified CompletionListener is notified.
* null if there was no previous
* value or the previous value is not available
*/
public abstract V getOldValue();
/**
* Whether the old value is available. The old value will be available
* for {@link CacheEntryUpdatedListener}, {@link CacheEntryExpiredListener}
* and {@link CacheEntryRemovedListener}
* if {@link CacheEntryListenerConfiguration#isOldValueRequired()} is true.
* The old value may be available for {@link CacheEntryUpdatedListener},
* {@link CacheEntryExpiredListener} and {@link CacheEntryRemovedListener}
* if {@link CacheEntryListenerConfiguration#isOldValueRequired()} is false.
*
* @return true if the old value is definitely available
*/
public abstract boolean isOldValueAvailable();
/**
* Gets the event type of this event
*
* @return the event type.
*/
public final EventType getEventType() {
return eventType;
}
}
```
`EventType` 定义如下:
```java
package javax.cache.event;
/**
* The type of event received by the listener.
*
* @author Greg Luck
* @since 1.0
*/
public enum EventType {
/**
* An event type indicating that the cache entry was created.
*/
CREATED,
/**
* An event type indicating that the cache entry was updated. i.e. a previous
* mapping existed
*/
UPDATED,
/**
* An event type indicating that the cache entry was removed.
*/
REMOVED,
/**
* An event type indicating that the cache entry has expired.
*/
EXPIRED
}
```
#### `CacheEntryEvent` 中 `getValue` 和 `getOldValue` 的可用性
下表总结了 `isOldValueRequired` 为 true 时,各个监听器调用 `getValue` 和 `getOldValue` 时的返回值。
|`CacheEntryEvent`|`CacheEntryCreatedListener`|`CacheEntryUpdatedListener`|`CacheEntryRemovedListener`
`CacheEntryExpiredListener`|
|---|---|---|---|
|`getValue`|新值|新值|旧值|
|`getOldValue`|`null`|旧值|旧值|
下表总结了 `isOldValueRequired` 为 false 时,各个监听器调用 `getValue` 和 `getOldValue` 时的返回值。
|`CacheEntryEvent`|`CacheEntryCreatedListener`|`CacheEntryUpdatedListener`|`CacheEntryRemovedListener`
`CacheEntryExpiredListener`|
|---|---|---|---|
|`getValue`|新值|新值|旧值或`null`|
|`getOldValue`|`null`|旧值或`null`|旧值`null`|
当 `isOldValueRequired` 为 false 时,缓存实现可以自由选择是否返回旧值。
### 缓存条目监听器
`CacheEntryListener` 通过 `CacheEntryListenerConfiguration` 注册到 `Cache` 中。`CacheEntryListener` 接口定义如下:
```java
package javax.cache.event;
import java.util.EventListener;
/**
* A tagging interface for cache entry listeners.
*
*
* Listeners follow the observer pattern. An exception thrown by a
* listener does not cause the cache operation to fail.
* true if the old value is required by the
* {@link CacheEntryListener}
*/
boolean isOldValueRequired();
/**
* Obtains the {@link Factory} for the {@link CacheEntryEventFilter} that should be
* applied prior to notifying the {@link CacheEntryListener}.
* null no filtering is applied and all appropriate events
* are notified.
*
* @return the {@link Factory} for the
* {@link CacheEntryEventFilter} or null
* if no filtering is required
*/
Factorytrue if the thread that created the event should block
*/
boolean isSynchronous();
}
```
为了便于使用,本规范提供了一个实现 `javax.cache.configuration.MutableCacheEntryListenerConfiguration`
### 监听器的调用
缓存监听器:
- 条目变更时被触发。
- 如果是同步的,对应一个指定的 key,事件处理的顺序是事件发生的顺序,在监听器处理完之前会阻塞调用线程。
- 如果是异步的,多个事件的遍历顺序未定义,但是对于同一个key 的事件,必须按照事件发生的顺序来处理。
监听器使用观察者模式,缓存监听器内的异常不会导致缓存操作失败。
监听器可能会导致死锁,对死锁的检测和响应取决于实现。
对于每个事件来说,特定的监听器最多只被调用一次。该监听器的调用指的是集群范围内的调用,而不是每个节点的。
监听器和原始的事件可以不在同一个进程。在分布式实现中,监听器可以位于任何位置。
监听器可能有对应的事件过滤器 `CacheEntryEventFilter`,这是 `CacheEntryListenerConfiguration` 配置的一部分。接口定义如下:
```java
package javax.cache.event;
/**
* A function that may be used to check {@link CacheEntryEvent}s prior to being
* dispatched to {@link CacheEntryListener}s.
* Effect of {@link MutableEntry} operations
* {@link javax.cache.Cache.Entry} access, via a call to
* {@link javax.cache.Cache.Entry#getValue()}, will behave as if
* {@link Cache#get(Object)} was called for the key. This includes updating
* necessary statistics, consulting the configured {@link ExpiryPolicy} and loading
* from a configured {@link javax.cache.integration.CacheLoader}.
* Effect of multiple {@link MutableEntry} operations performed by one {@link
* EntryProcessor}
* Only the net effect of multiple operations has visibility outside of the Entry
* Processor. The entry is locked by the entry processor for the entire scope
* of the entry processor, so intermediate effects are not visible.
* Example 1
* In this example, an {@link EntryProcessor} calls:
*
*
* This will have the following {@link Cache} effects:
*
* Final value of the cache: last setValue
* Statistics: one get and one put as the second get and the first put are
* internal to the EntryProcessor.
* Listeners: second put will cause either a put or an update depending on whether
* there was an initial value for the entry.
* CacheLoader: Invoked by the first get only if the entry is not present, a
* loader was registered and read through is enabled.
* CacheWriter: Invoked by the second put only as the first put was internal to
* the Entry Processor.
* ExpiryPolicy: The first get and the second put only are visible to the
* ExpiryPolicy.
*
* Example 2
* In this example, an {@link EntryProcessor} calls:
*
*
* This will have the following {@link Cache} effects:
*
* Final value of the cache: last setValue
* Statistics: one get and one put as the second get and the first put are
* internal to the EntryProcessor.
* Listeners: second put will cause either a put or an update depending on whether
* there was an initial value for the entry.
* CacheLoader: Invoked by the first get only if the entry is not present, a loader
* was registered and read through is enabled.
* CacheWriter: Invoked by the second put only as the first put was internal to
* the Entry Processor.
* ExpiryPolicy: The first get and the second put only are visible to the
* ExpiryPolicy.
*
* Example 3
* In this example, an {@link EntryProcessor} calls:
*
*
* This will have the following {@link Cache} effects:
*
* Final value of the cache: the entry is removed if it was present
* Statistics: one get and one remove as the second get and the two puts are
* internal to the EntryProcessor.
* Listeners: remove if there was initial value in the cache, otherwise no
* listener invoked.
*
CacheLoader: Invoked by the first get only if the entry is not present,
* a loader was registered and read through is enabled.
*
CacheWriter: Invoked by the remove only as the two puts are internal to
* the Entry Processor, provided that the first #getValue was non-null.
* ExpiryPolicy: The first get only is visible to the ExpiryPolicy. There is no
* remove event in ExpiryPolicy.
*
* @param null value for a key.
* @throws NullPointerException if keys or {@link EntryProcessor} are null
* @throws IllegalStateException if the cache is {@link #isClosed()}
* @throws ClassCastException if the implementation is configured to perform
* runtime-type-checking, and the key or value
* types are incompatible with those that have been
* configured for the {@link Cache}
* @see EntryProcessor
*/
* META-INF/services/javax.cache.spi.CachingProvider
*
* This file must be resolvable via the class path.
* org.jsr107.ri.RICachingProvider
* javax.cache.spi.cachingprovider, that implementation will be used
* as the default {@link CachingProvider}.
*
*
* To request a specific {@link CachingProvider} implementation, a developer
* should use either the {@link #getCachingProvider(String)} or
* {@link #getCachingProvider(String, ClassLoader)} method.
* javax.cache.spi.cachingprovider constant.
*/
public static final String JAVAX_CACHE_CACHING_PROVIDER = "javax.cache" +
".spi.CachingProvider";
/**
* The {@link CachingProviderRegistry} that tracks the {@link CachingProvider}s.
*/
private static final CachingProviderRegistry CACHING_PROVIDERS =
new CachingProviderRegistry();
/**
* No public constructor as all methods are static.
*/
private Caching() {
}
/**
* Obtains the {@link ClassLoader} to use for API methods that don't
* explicitly require a {@link ClassLoader} but internally require one.
* null if the
* calling {@link Thread#getContextClassLoader()} should
* be used
*/
public static void setDefaultClassLoader(ClassLoader classLoader) {
CACHING_PROVIDERS.setDefaultClassLoader(classLoader);
}
/**
* Obtains the default {@link CachingProvider} available via the
* {@link #getDefaultClassLoader()}.
*
* @return the {@link CachingProvider}
* @throws CacheException should zero, or more than one
* {@link CachingProvider} be available on the
* classpath, or it could not be loaded
* @throws SecurityException when the operation could not be performed
* due to the current security settings
*/
public static CachingProvider getCachingProvider() {
return CACHING_PROVIDERS.getCachingProvider();
}
/**
* Obtains the single {@link CachingProvider} visible to the specified
* {@link ClassLoader}.
*
* @param classLoader the {@link ClassLoader} to use for loading the
* {@link CachingProvider}
* @return the {@link CachingProvider}
* @throws CacheException should zero, or more than one
* {@link CachingProvider} be available on the
* classpath, or it could not be loaded
* @throws SecurityException when the operation could not be performed
* due to the current security settings
* @see #getCachingProviders(ClassLoader)
*/
public static CachingProvider getCachingProvider(ClassLoader classLoader) {
return CACHING_PROVIDERS.getCachingProvider(classLoader);
}
/**
* Obtains the {@link CachingProvider}s that are available via the
* {@link #getDefaultClassLoader()}.
* javax.cache.spi.cachingprovider system property is defined,
* only that {@link CachingProvider} specified by that property is returned.
* Otherwise all {@link CachingProvider}s that are available via a
* {@link ServiceLoader} for {@link CachingProvider}s using the default
* {@link ClassLoader} (including those previously requested via
* {@link #getCachingProvider(String)}) are returned.
*
* @return an {@link Iterable} of {@link CachingProvider}s loaded by the
* specified {@link ClassLoader}
*/
public static Iterablejavax.cache.spi.cachingprovider system property is defined,
* only that {@link CachingProvider} specified by that property is returned.
* Otherwise all {@link CachingProvider}s that are available via a
* {@link ServiceLoader} for {@link CachingProvider}s using the specified
* {@link ClassLoader} (including those previously requested via
* {@link #getCachingProvider(String, ClassLoader)}) are returned.
*
* @param classLoader the {@link ClassLoader} of the returned
* {@link CachingProvider}s
* @return an {@link Iterable} of {@link CachingProvider}s loaded by the
* specified {@link ClassLoader}
*/
public static IterableCachingProvider and CacheManager
* . For the full range of Cache look up methods see
* {@link CacheManager}.
* null.
* @param