Added "transactionAware" bean property to EhCacheCacheManager and JCacheCacheManager
In the course of this enhancement, the "cache.ehcache" and "cache.jcache" packages moved from spring-context to the spring-context-support module, expecting further transaction-related functionality. Also aligns with the presence of Spring's Quartz support in the spring-context-support module, since Quartz and EHCache are sort of sister projects at Terracotta now. Issue: SPR-9966
This commit is contained in:
77
spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java
vendored
Normal file
77
spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.ehcache;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Element;
|
||||
import net.sf.ehcache.Status;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link Cache} implementation on top of an {@link Ehcache} instance.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class EhCacheCache implements Cache {
|
||||
|
||||
private final Ehcache cache;
|
||||
|
||||
|
||||
/**
|
||||
* Create an {@link EhCacheCache} instance.
|
||||
* @param ehcache backing Ehcache instance
|
||||
*/
|
||||
public EhCacheCache(Ehcache ehcache) {
|
||||
Assert.notNull(ehcache, "Ehcache must not be null");
|
||||
Status status = ehcache.getStatus();
|
||||
Assert.isTrue(Status.STATUS_ALIVE.equals(status),
|
||||
"An 'alive' Ehcache is required - current cache is " + status.toString());
|
||||
this.cache = ehcache;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return this.cache.getName();
|
||||
}
|
||||
|
||||
public Ehcache getNativeCache() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
public ValueWrapper get(Object key) {
|
||||
Element element = this.cache.get(key);
|
||||
return (element != null ? new SimpleValueWrapper(element.getObjectValue()) : null);
|
||||
}
|
||||
|
||||
public void put(Object key, Object value) {
|
||||
this.cache.put(new Element(key, value));
|
||||
}
|
||||
|
||||
public void evict(Object key) {
|
||||
this.cache.remove(key);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.cache.removeAll();
|
||||
}
|
||||
|
||||
}
|
||||
102
spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java
vendored
Normal file
102
spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.ehcache;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Status;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* CacheManager backed by an EhCache {@link net.sf.ehcache.CacheManager}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class EhCacheCacheManager extends AbstractTransactionSupportingCacheManager {
|
||||
|
||||
private net.sf.ehcache.CacheManager cacheManager;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new EhCacheCacheManager, setting the target EhCache CacheManager
|
||||
* through the {@link #setCacheManager} bean property.
|
||||
*/
|
||||
public EhCacheCacheManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new EhCacheCacheManager for the given backing EhCache.
|
||||
* @param cacheManager the backing EhCache {@link net.sf.ehcache.CacheManager}
|
||||
*/
|
||||
public EhCacheCacheManager(net.sf.ehcache.CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the backing EhCache {@link net.sf.ehcache.CacheManager}.
|
||||
*/
|
||||
public void setCacheManager(net.sf.ehcache.CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the backing EhCache {@link net.sf.ehcache.CacheManager}.
|
||||
*/
|
||||
public net.sf.ehcache.CacheManager getCacheManager() {
|
||||
return this.cacheManager;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Collection<Cache> loadCaches() {
|
||||
Assert.notNull(this.cacheManager, "A backing EhCache CacheManager is required");
|
||||
Status status = this.cacheManager.getStatus();
|
||||
Assert.isTrue(Status.STATUS_ALIVE.equals(status),
|
||||
"An 'alive' EhCache CacheManager is required - current cache is " + status.toString());
|
||||
|
||||
String[] names = this.cacheManager.getCacheNames();
|
||||
Collection<Cache> caches = new LinkedHashSet<Cache>(names.length);
|
||||
for (String name : names) {
|
||||
caches.add(new EhCacheCache(this.cacheManager.getEhcache(name)));
|
||||
}
|
||||
return caches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cache getCache(String name) {
|
||||
Cache cache = super.getCache(name);
|
||||
if (cache == null) {
|
||||
// check the EhCache cache again
|
||||
// (in case the cache was added at runtime)
|
||||
Ehcache ehcache = this.cacheManager.getEhcache(name);
|
||||
if (ehcache != null) {
|
||||
cache = new EhCacheCache(ehcache);
|
||||
addCache(cache);
|
||||
}
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
}
|
||||
427
spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java
vendored
Normal file
427
spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java
vendored
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.ehcache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheException;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
|
||||
import net.sf.ehcache.constructs.blocking.BlockingCache;
|
||||
import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
|
||||
import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
|
||||
import net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory;
|
||||
import net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache;
|
||||
import net.sf.ehcache.event.CacheEventListener;
|
||||
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} that creates a named EHCache {@link net.sf.ehcache.Cache} instance
|
||||
* (or a decorator that implements the {@link net.sf.ehcache.Ehcache} interface),
|
||||
* representing a cache region within an EHCache {@link net.sf.ehcache.CacheManager}.
|
||||
*
|
||||
* <p>If the specified named cache is not configured in the cache configuration descriptor,
|
||||
* this FactoryBean will construct an instance of a Cache with the provided name and the
|
||||
* specified cache properties and add it to the CacheManager for later retrieval. If some
|
||||
* or all properties are not set at configuration time, this FactoryBean will use defaults.
|
||||
*
|
||||
* <p>Note: If the named Cache instance is found, the properties will be ignored and the
|
||||
* Cache instance will be retrieved from the CacheManager.
|
||||
*
|
||||
* <p>Note: As of Spring 3.0, Spring's EHCache support requires EHCache 1.3 or higher.
|
||||
|
||||
* @author Dmitriy Kopylenko
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1.1
|
||||
* @see #setCacheManager
|
||||
* @see EhCacheManagerFactoryBean
|
||||
* @see net.sf.ehcache.Cache
|
||||
*/
|
||||
public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware, InitializingBean {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private CacheManager cacheManager;
|
||||
|
||||
private String cacheName;
|
||||
|
||||
private int maxElementsInMemory = 10000;
|
||||
|
||||
private int maxElementsOnDisk = 10000000;
|
||||
|
||||
private MemoryStoreEvictionPolicy memoryStoreEvictionPolicy = MemoryStoreEvictionPolicy.LRU;
|
||||
|
||||
private boolean overflowToDisk = true;
|
||||
|
||||
private boolean eternal = false;
|
||||
|
||||
private int timeToLive = 120;
|
||||
|
||||
private int timeToIdle = 120;
|
||||
|
||||
private boolean diskPersistent = false;
|
||||
|
||||
private int diskExpiryThreadIntervalSeconds = 120;
|
||||
|
||||
private int diskSpoolBufferSize = 0;
|
||||
|
||||
private boolean clearOnFlush = true;
|
||||
|
||||
private boolean blocking = false;
|
||||
|
||||
private CacheEntryFactory cacheEntryFactory;
|
||||
|
||||
private BootstrapCacheLoader bootstrapCacheLoader;
|
||||
|
||||
private Set<CacheEventListener> cacheEventListeners;
|
||||
|
||||
private boolean statisticsEnabled = false;
|
||||
|
||||
private boolean sampledStatisticsEnabled = false;
|
||||
|
||||
private boolean disabled = false;
|
||||
|
||||
private String beanName;
|
||||
|
||||
private Ehcache cache;
|
||||
|
||||
|
||||
/**
|
||||
* Set a CacheManager from which to retrieve a named Cache instance.
|
||||
* By default, <code>CacheManager.getInstance()</code> will be called.
|
||||
* <p>Note that in particular for persistent caches, it is advisable to
|
||||
* properly handle the shutdown of the CacheManager: Set up a separate
|
||||
* EhCacheManagerFactoryBean and pass a reference to this bean property.
|
||||
* <p>A separate EhCacheManagerFactoryBean is also necessary for loading
|
||||
* EHCache configuration from a non-default config location.
|
||||
* @see EhCacheManagerFactoryBean
|
||||
* @see net.sf.ehcache.CacheManager#getInstance
|
||||
*/
|
||||
public void setCacheManager(CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a name for which to retrieve or create a cache instance.
|
||||
* Default is the bean name of this EhCacheFactoryBean.
|
||||
*/
|
||||
public void setCacheName(String cacheName) {
|
||||
this.cacheName = cacheName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the maximum number of cached objects in memory.
|
||||
* Default is 10000 elements.
|
||||
*/
|
||||
public void setMaxElementsInMemory(int maxElementsInMemory) {
|
||||
this.maxElementsInMemory = maxElementsInMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the maximum number of cached objects on disk.
|
||||
* Default is 10000000 elements.
|
||||
*/
|
||||
public void setMaxElementsOnDisk(int maxElementsOnDisk) {
|
||||
this.maxElementsOnDisk = maxElementsOnDisk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the memory style eviction policy for this cache.
|
||||
* <p>Supported values are "LRU", "LFU" and "FIFO", according to the
|
||||
* constants defined in EHCache's MemoryStoreEvictionPolicy class.
|
||||
* Default is "LRU".
|
||||
*/
|
||||
public void setMemoryStoreEvictionPolicy(MemoryStoreEvictionPolicy memoryStoreEvictionPolicy) {
|
||||
Assert.notNull(memoryStoreEvictionPolicy, "memoryStoreEvictionPolicy must not be null");
|
||||
this.memoryStoreEvictionPolicy = memoryStoreEvictionPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether elements can overflow to disk when the in-memory cache
|
||||
* has reached the maximum size limit. Default is "true".
|
||||
*/
|
||||
public void setOverflowToDisk(boolean overflowToDisk) {
|
||||
this.overflowToDisk = overflowToDisk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether elements are considered as eternal. If "true", timeouts
|
||||
* are ignored and the element is never expired. Default is "false".
|
||||
*/
|
||||
public void setEternal(boolean eternal) {
|
||||
this.eternal = eternal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time in seconds to live for an element before it expires,
|
||||
* i.e. the maximum time between creation time and when an element expires.
|
||||
* <p>This is only used if the element is not eternal. Default is 120 seconds.
|
||||
*/
|
||||
public void setTimeToLive(int timeToLive) {
|
||||
this.timeToLive = timeToLive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time in seconds to idle for an element before it expires, that is,
|
||||
* the maximum amount of time between accesses before an element expires.
|
||||
* <p>This is only used if the element is not eternal. Default is 120 seconds.
|
||||
*/
|
||||
public void setTimeToIdle(int timeToIdle) {
|
||||
this.timeToIdle = timeToIdle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the disk store persists between restarts of the Virtual Machine.
|
||||
* Default is "false".
|
||||
*/
|
||||
public void setDiskPersistent(boolean diskPersistent) {
|
||||
this.diskPersistent = diskPersistent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of seconds between runs of the disk expiry thread.
|
||||
* Default is 120 seconds.
|
||||
*/
|
||||
public void setDiskExpiryThreadIntervalSeconds(int diskExpiryThreadIntervalSeconds) {
|
||||
this.diskExpiryThreadIntervalSeconds = diskExpiryThreadIntervalSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of memory to allocate the write buffer for puts to the disk store.
|
||||
* Default is 0.
|
||||
*/
|
||||
public void setDiskSpoolBufferSize(int diskSpoolBufferSize) {
|
||||
this.diskSpoolBufferSize = diskSpoolBufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the memory store should be cleared when flush is called on the cache.
|
||||
* Default is "true".
|
||||
*/
|
||||
public void setClearOnFlush(boolean clearOnFlush) {
|
||||
this.clearOnFlush = clearOnFlush;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to use a blocking cache that lets read attempts block
|
||||
* until the requested element is created.
|
||||
* <p>If you intend to build a self-populating blocking cache,
|
||||
* consider specifying a {@link #setCacheEntryFactory CacheEntryFactory}.
|
||||
* @see net.sf.ehcache.constructs.blocking.BlockingCache
|
||||
* @see #setCacheEntryFactory
|
||||
*/
|
||||
public void setBlocking(boolean blocking) {
|
||||
this.blocking = blocking;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an EHCache {@link net.sf.ehcache.constructs.blocking.CacheEntryFactory}
|
||||
* to use for a self-populating cache. If such a factory is specified,
|
||||
* the cache will be decorated with EHCache's
|
||||
* {@link net.sf.ehcache.constructs.blocking.SelfPopulatingCache}.
|
||||
* <p>The specified factory can be of type
|
||||
* {@link net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory},
|
||||
* which will lead to the use of an
|
||||
* {@link net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache}.
|
||||
* <p>Note: Any such self-populating cache is automatically a blocking cache.
|
||||
* @see net.sf.ehcache.constructs.blocking.SelfPopulatingCache
|
||||
* @see net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache
|
||||
* @see net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory
|
||||
*/
|
||||
public void setCacheEntryFactory(CacheEntryFactory cacheEntryFactory) {
|
||||
this.cacheEntryFactory = cacheEntryFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an EHCache {@link net.sf.ehcache.bootstrap.BootstrapCacheLoader}
|
||||
* for this cache, if any.
|
||||
*/
|
||||
public void setBootstrapCacheLoader(BootstrapCacheLoader bootstrapCacheLoader) {
|
||||
this.bootstrapCacheLoader = bootstrapCacheLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify EHCache {@link net.sf.ehcache.event.CacheEventListener cache event listeners}
|
||||
* to registered with this cache.
|
||||
*/
|
||||
public void setCacheEventListeners(Set<CacheEventListener> cacheEventListeners) {
|
||||
this.cacheEventListeners = cacheEventListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to enable EhCache statistics on this cache.
|
||||
* @see net.sf.ehcache.Cache#setStatisticsEnabled
|
||||
*/
|
||||
public void setStatisticsEnabled(boolean statisticsEnabled) {
|
||||
this.statisticsEnabled = statisticsEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to enable EhCache's sampled statistics on this cache.
|
||||
* @see net.sf.ehcache.Cache#setSampledStatisticsEnabled
|
||||
*/
|
||||
public void setSampledStatisticsEnabled(boolean sampledStatisticsEnabled) {
|
||||
this.sampledStatisticsEnabled = sampledStatisticsEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this cache should be marked as disabled.
|
||||
* @see net.sf.ehcache.Cache#setDisabled
|
||||
*/
|
||||
public void setDisabled(boolean disabled) {
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
public void setBeanName(String name) {
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
|
||||
public void afterPropertiesSet() throws CacheException, IOException {
|
||||
// If no CacheManager given, fetch the default.
|
||||
if (this.cacheManager == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Using default EHCache CacheManager for cache region '" + this.cacheName + "'");
|
||||
}
|
||||
this.cacheManager = CacheManager.getInstance();
|
||||
}
|
||||
|
||||
// If no cache name given, use bean name as cache name.
|
||||
if (this.cacheName == null) {
|
||||
this.cacheName = this.beanName;
|
||||
}
|
||||
|
||||
// Fetch cache region: If none with the given name exists,
|
||||
// create one on the fly.
|
||||
Ehcache rawCache;
|
||||
if (this.cacheManager.cacheExists(this.cacheName)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Using existing EHCache cache region '" + this.cacheName + "'");
|
||||
}
|
||||
rawCache = this.cacheManager.getEhcache(this.cacheName);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Creating new EHCache cache region '" + this.cacheName + "'");
|
||||
}
|
||||
rawCache = createCache();
|
||||
this.cacheManager.addCache(rawCache);
|
||||
}
|
||||
|
||||
if (this.cacheEventListeners != null) {
|
||||
for (CacheEventListener listener : this.cacheEventListeners) {
|
||||
rawCache.getCacheEventNotificationService().registerListener(listener);
|
||||
}
|
||||
}
|
||||
if (this.statisticsEnabled) {
|
||||
rawCache.setStatisticsEnabled(true);
|
||||
}
|
||||
if (this.sampledStatisticsEnabled) {
|
||||
rawCache.setSampledStatisticsEnabled(true);
|
||||
}
|
||||
if (this.disabled) {
|
||||
rawCache.setDisabled(true);
|
||||
}
|
||||
|
||||
// Decorate cache if necessary.
|
||||
Ehcache decoratedCache = decorateCache(rawCache);
|
||||
if (decoratedCache != rawCache) {
|
||||
this.cacheManager.replaceCacheWithDecoratedCache(rawCache, decoratedCache);
|
||||
}
|
||||
this.cache = decoratedCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a raw Cache object based on the configuration of this FactoryBean.
|
||||
*/
|
||||
protected Cache createCache() {
|
||||
// Only call EHCache 1.6 constructor if actually necessary (for compatibility with EHCache 1.3+)
|
||||
return (!this.clearOnFlush) ?
|
||||
new Cache(this.cacheName, this.maxElementsInMemory, this.memoryStoreEvictionPolicy,
|
||||
this.overflowToDisk, null, this.eternal, this.timeToLive, this.timeToIdle,
|
||||
this.diskPersistent, this.diskExpiryThreadIntervalSeconds, null,
|
||||
this.bootstrapCacheLoader, this.maxElementsOnDisk, this.diskSpoolBufferSize,
|
||||
this.clearOnFlush) :
|
||||
new Cache(this.cacheName, this.maxElementsInMemory, this.memoryStoreEvictionPolicy,
|
||||
this.overflowToDisk, null, this.eternal, this.timeToLive, this.timeToIdle,
|
||||
this.diskPersistent, this.diskExpiryThreadIntervalSeconds, null,
|
||||
this.bootstrapCacheLoader, this.maxElementsOnDisk, this.diskSpoolBufferSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorate the given Cache, if necessary.
|
||||
* @param cache the raw Cache object, based on the configuration of this FactoryBean
|
||||
* @return the (potentially decorated) cache object to be registered with the CacheManager
|
||||
*/
|
||||
protected Ehcache decorateCache(Ehcache cache) {
|
||||
if (this.cacheEntryFactory != null) {
|
||||
if (this.cacheEntryFactory instanceof UpdatingCacheEntryFactory) {
|
||||
return new UpdatingSelfPopulatingCache(cache, (UpdatingCacheEntryFactory) this.cacheEntryFactory);
|
||||
}
|
||||
else {
|
||||
return new SelfPopulatingCache(cache, this.cacheEntryFactory);
|
||||
}
|
||||
}
|
||||
if (this.blocking) {
|
||||
return new BlockingCache(cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
public Ehcache getObject() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Predict the particular {@code Ehcache} implementation that will be returned from
|
||||
* {@link #getObject()} based on logic in {@link #createCache()} and
|
||||
* {@link #decorateCache(Ehcache)} as orchestrated by {@link #afterPropertiesSet()}.
|
||||
*/
|
||||
public Class<? extends Ehcache> getObjectType() {
|
||||
if (this.cache != null) {
|
||||
return this.cache.getClass();
|
||||
}
|
||||
if (this.cacheEntryFactory != null) {
|
||||
if (this.cacheEntryFactory instanceof UpdatingCacheEntryFactory) {
|
||||
return UpdatingSelfPopulatingCache.class;
|
||||
}
|
||||
else {
|
||||
return SelfPopulatingCache.class;
|
||||
}
|
||||
}
|
||||
if (this.blocking) {
|
||||
return BlockingCache.class;
|
||||
}
|
||||
return Cache.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.ehcache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import net.sf.ehcache.CacheException;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} that exposes an EHCache {@link net.sf.ehcache.CacheManager}
|
||||
* instance (independent or shared), configured from a specified config location.
|
||||
*
|
||||
* <p>If no config location is specified, a CacheManager will be configured from
|
||||
* "ehcache.xml" in the root of the class path (that is, default EHCache initialization
|
||||
* - as defined in the EHCache docs - will apply).
|
||||
*
|
||||
* <p>Setting up a separate EhCacheManagerFactoryBean is also advisable when using
|
||||
* EhCacheFactoryBean, as it provides a (by default) independent CacheManager instance
|
||||
* and cares for proper shutdown of the CacheManager. EhCacheManagerFactoryBean is
|
||||
* also necessary for loading EHCache configuration from a non-default config location.
|
||||
*
|
||||
* <p>Note: As of Spring 3.0, Spring's EHCache support requires EHCache 1.3 or higher.
|
||||
*
|
||||
* @author Dmitriy Kopylenko
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1.1
|
||||
* @see #setConfigLocation
|
||||
* @see #setShared
|
||||
* @see EhCacheFactoryBean
|
||||
* @see net.sf.ehcache.CacheManager
|
||||
*/
|
||||
public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, InitializingBean, DisposableBean {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Resource configLocation;
|
||||
|
||||
private boolean shared = false;
|
||||
|
||||
private String cacheManagerName;
|
||||
|
||||
private CacheManager cacheManager;
|
||||
|
||||
|
||||
/**
|
||||
* Set the location of the EHCache config file. A typical value is "/WEB-INF/ehcache.xml".
|
||||
* <p>Default is "ehcache.xml" in the root of the class path, or if not found,
|
||||
* "ehcache-failsafe.xml" in the EHCache jar (default EHCache initialization).
|
||||
* @see net.sf.ehcache.CacheManager#create(java.io.InputStream)
|
||||
* @see net.sf.ehcache.CacheManager#CacheManager(java.io.InputStream)
|
||||
*/
|
||||
public void setConfigLocation(Resource configLocation) {
|
||||
this.configLocation = configLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the EHCache CacheManager should be shared (as a singleton at the VM level)
|
||||
* or independent (typically local within the application). Default is "false", creating
|
||||
* an independent instance.
|
||||
* @see net.sf.ehcache.CacheManager#create()
|
||||
* @see net.sf.ehcache.CacheManager#CacheManager()
|
||||
*/
|
||||
public void setShared(boolean shared) {
|
||||
this.shared = shared;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the EHCache CacheManager (if a specific name is desired).
|
||||
* @see net.sf.ehcache.CacheManager#setName(String)
|
||||
*/
|
||||
public void setCacheManagerName(String cacheManagerName) {
|
||||
this.cacheManagerName = cacheManagerName;
|
||||
}
|
||||
|
||||
|
||||
public void afterPropertiesSet() throws IOException, CacheException {
|
||||
logger.info("Initializing EHCache CacheManager");
|
||||
if (this.configLocation != null) {
|
||||
InputStream is = this.configLocation.getInputStream();
|
||||
try {
|
||||
this.cacheManager = (this.shared ? CacheManager.create(is) : new CacheManager(is));
|
||||
}
|
||||
finally {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.cacheManager = (this.shared ? CacheManager.create() : new CacheManager());
|
||||
}
|
||||
if (this.cacheManagerName != null) {
|
||||
this.cacheManager.setName(this.cacheManagerName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public CacheManager getObject() {
|
||||
return this.cacheManager;
|
||||
}
|
||||
|
||||
public Class<? extends CacheManager> getObjectType() {
|
||||
return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class);
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void destroy() {
|
||||
logger.info("Shutting down EHCache CacheManager");
|
||||
this.cacheManager.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
7
spring-context-support/src/main/java/org/springframework/cache/ehcache/package-info.java
vendored
Normal file
7
spring-context-support/src/main/java/org/springframework/cache/ehcache/package-info.java
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Support classes for the open source cache
|
||||
* <a href="http://ehcache.sourceforge.net">EhCache</a>,
|
||||
* allowing to set up an EhCache CacheManager and Caches
|
||||
* as beans in a Spring context.
|
||||
*/
|
||||
package org.springframework.cache.ehcache;
|
||||
131
spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java
vendored
Normal file
131
spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.jcache;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.cache.Status;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.cache.Cache} implementation on top of a
|
||||
* {@link javax.cache.Cache} instance.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.2
|
||||
*/
|
||||
public class JCacheCache implements Cache {
|
||||
|
||||
private static final Object NULL_HOLDER = new NullHolder();
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final javax.cache.Cache cache;
|
||||
|
||||
private final boolean allowNullValues;
|
||||
|
||||
|
||||
/**
|
||||
* Create an {@link org.springframework.cache.jcache.JCacheCache} instance.
|
||||
* @param jcache backing JCache Cache instance
|
||||
*/
|
||||
public JCacheCache(javax.cache.Cache<?,?> jcache) {
|
||||
this(jcache, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link org.springframework.cache.jcache.JCacheCache} instance.
|
||||
* @param jcache backing JCache Cache instance
|
||||
* @param allowNullValues whether to accept and convert null values for this cache
|
||||
*/
|
||||
public JCacheCache(javax.cache.Cache<?,?> jcache, boolean allowNullValues) {
|
||||
Assert.notNull(jcache, "Cache must not be null");
|
||||
Status status = jcache.getStatus();
|
||||
Assert.isTrue(Status.STARTED.equals(status),
|
||||
"A 'started' cache is required - current cache is " + status.toString());
|
||||
this.cache = jcache;
|
||||
this.allowNullValues = allowNullValues;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return this.cache.getName();
|
||||
}
|
||||
|
||||
public javax.cache.Cache<?,?> getNativeCache() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
public boolean isAllowNullValues() {
|
||||
return this.allowNullValues;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ValueWrapper get(Object key) {
|
||||
Object value = this.cache.get(key);
|
||||
return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void put(Object key, Object value) {
|
||||
this.cache.put(key, toStoreValue(value));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void evict(Object key) {
|
||||
this.cache.remove(key);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.cache.removeAll();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the given value from the internal store to a user value
|
||||
* returned from the get method (adapting <code>null</code>).
|
||||
* @param storeValue the store value
|
||||
* @return the value to return to the user
|
||||
*/
|
||||
protected Object fromStoreValue(Object storeValue) {
|
||||
if (this.allowNullValues && storeValue == NULL_HOLDER) {
|
||||
return null;
|
||||
}
|
||||
return storeValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given user value, as passed into the put method,
|
||||
* to a value in the internal store (adapting <code>null</code>).
|
||||
* @param userValue the given user value
|
||||
* @return the value to store
|
||||
*/
|
||||
protected Object toStoreValue(Object userValue) {
|
||||
if (this.allowNullValues && userValue == null) {
|
||||
return NULL_HOLDER;
|
||||
}
|
||||
return userValue;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class NullHolder implements Serializable {
|
||||
}
|
||||
|
||||
}
|
||||
120
spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCacheManager.java
vendored
Normal file
120
spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCacheManager.java
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.jcache;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import javax.cache.CacheManager;
|
||||
import javax.cache.Status;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.cache.CacheManager} implementation
|
||||
* backed by a JCache {@link javax.cache.CacheManager}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.2
|
||||
*/
|
||||
public class JCacheCacheManager extends AbstractTransactionSupportingCacheManager {
|
||||
|
||||
private javax.cache.CacheManager cacheManager;
|
||||
|
||||
private boolean allowNullValues = true;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new JCacheCacheManager, setting the target JCache CacheManager
|
||||
* through the {@link #setCacheManager} bean property.
|
||||
*/
|
||||
public JCacheCacheManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JCacheCacheManager for the given backing JCache.
|
||||
* @param cacheManager the backing JCache {@link javax.cache.CacheManager}
|
||||
*/
|
||||
public JCacheCacheManager(CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the backing JCache {@link javax.cache.CacheManager}.
|
||||
*/
|
||||
public void setCacheManager(javax.cache.CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the backing JCache {@link javax.cache.CacheManager}.
|
||||
*/
|
||||
public javax.cache.CacheManager getCacheManager() {
|
||||
return this.cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to accept and convert null values for all caches
|
||||
* in this cache manager.
|
||||
* <p>Default is "true", despite JSR-107 itself not supporting null values.
|
||||
* An internal holder object will be used to store user-level null values.
|
||||
*/
|
||||
public void setAllowNullValues(boolean allowNullValues) {
|
||||
this.allowNullValues = allowNullValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this cache manager accepts and converts null values
|
||||
* for all of its caches.
|
||||
*/
|
||||
public boolean isAllowNullValues() {
|
||||
return this.allowNullValues;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Collection<Cache> loadCaches() {
|
||||
Assert.notNull(this.cacheManager, "A backing CacheManager is required");
|
||||
Status status = this.cacheManager.getStatus();
|
||||
Assert.isTrue(Status.STARTED.equals(status),
|
||||
"A 'started' JCache CacheManager is required - current cache is " + status.toString());
|
||||
|
||||
Collection<Cache> caches = new LinkedHashSet<Cache>();
|
||||
for (javax.cache.Cache<?,?> jcache : this.cacheManager.getCaches()) {
|
||||
caches.add(new JCacheCache(jcache, this.allowNullValues));
|
||||
}
|
||||
return caches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cache getCache(String name) {
|
||||
Cache cache = super.getCache(name);
|
||||
if (cache == null) {
|
||||
// check the JCache cache again
|
||||
// (in case the cache was added at runtime)
|
||||
javax.cache.Cache<?,?> jcache = this.cacheManager.getCache(name);
|
||||
if (jcache != null) {
|
||||
cache = new JCacheCache(jcache, this.allowNullValues);
|
||||
addCache(cache);
|
||||
}
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.jcache;
|
||||
|
||||
import javax.cache.CacheManager;
|
||||
import javax.cache.Caching;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} for a JCache {@link javax.cache.CacheManager},
|
||||
* obtaining a pre-defined CacheManager by name through the standard
|
||||
* JCache {@link javax.cache.Caching} class.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.2
|
||||
* @see javax.cache.Caching#getCacheManager()
|
||||
* @see javax.cache.Caching#getCacheManager(String)
|
||||
*/
|
||||
public class JCacheManagerFactoryBean
|
||||
implements FactoryBean<CacheManager>, BeanClassLoaderAware, InitializingBean, DisposableBean {
|
||||
|
||||
private String cacheManagerName = Caching.DEFAULT_CACHE_MANAGER_NAME;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private CacheManager cacheManager;
|
||||
|
||||
|
||||
/**
|
||||
* Specify the name of the desired CacheManager.
|
||||
* Default is JCache's default.
|
||||
* @see Caching#DEFAULT_CACHE_MANAGER_NAME
|
||||
*/
|
||||
public void setCacheManagerName(String cacheManagerName) {
|
||||
this.cacheManagerName = cacheManagerName;
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
this.cacheManager = (this.beanClassLoader != null ?
|
||||
Caching.getCacheManager(this.beanClassLoader, this.cacheManagerName) :
|
||||
Caching.getCacheManager(this.cacheManagerName));
|
||||
}
|
||||
|
||||
|
||||
public CacheManager getObject() {
|
||||
return this.cacheManager;
|
||||
}
|
||||
|
||||
public Class<?> getObjectType() {
|
||||
return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class);
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void destroy() {
|
||||
this.cacheManager.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
7
spring-context-support/src/main/java/org/springframework/cache/jcache/package-info.java
vendored
Normal file
7
spring-context-support/src/main/java/org/springframework/cache/jcache/package-info.java
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Implementation package for JSR-107 (javax.cache aka "JCache") based caches.
|
||||
* Provides a {@link org.springframework.cache.CacheManager CacheManager}
|
||||
* and {@link org.springframework.cache.Cache Cache} implementation for
|
||||
* use in a Spring context, using a JSR-107 compliant cache provider.
|
||||
*/
|
||||
package org.springframework.cache.jcache;
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.transaction;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.support.AbstractCacheManager;
|
||||
|
||||
/**
|
||||
* Base class for CacheManager implementations that want to support built-in
|
||||
* awareness of Spring-managed transactions. This usually needs to be switched
|
||||
* on explicitly through the {@link #setTransactionAware} bean property.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.2
|
||||
* @see #setTransactionAware
|
||||
* @see TransactionAwareCacheDecorator
|
||||
* @see TransactionAwareCacheManagerProxy
|
||||
*/
|
||||
public abstract class AbstractTransactionSupportingCacheManager extends AbstractCacheManager {
|
||||
|
||||
private boolean transactionAware = false;
|
||||
|
||||
|
||||
/**
|
||||
* Set whether this CacheManager should expose transaction-aware Cache objects.
|
||||
* <p>Default is "false". Set this to "true" to synchronize cache put/evict
|
||||
* operations with ongoing Spring-managed transactions, performing the actual cache
|
||||
* put/evict operation only in the after-commit phase of a successful transaction.
|
||||
*/
|
||||
public void setTransactionAware(boolean transactionAware) {
|
||||
this.transactionAware = transactionAware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this CacheManager has been configured to be transaction-aware.
|
||||
*/
|
||||
public boolean isTransactionAware() {
|
||||
return this.transactionAware;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Cache decorateCache(Cache cache) {
|
||||
return (isTransactionAware() ? new TransactionAwareCacheDecorator(cache) : cache);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.transaction;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Cache decorator which synchronizes its {@link #put} and {@link #evict} operations with
|
||||
* Spring-managed transactions (through Spring's {@link TransactionSynchronizationManager},
|
||||
* performing the actual cache put/evict operation only in the after-commit phase of a
|
||||
* successful transaction. If no transaction is active, {@link #put} and {@link #evict}
|
||||
* operations will be performed immediately, as usual.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.2
|
||||
* @see TransactionAwareCacheManagerProxy
|
||||
*/
|
||||
public class TransactionAwareCacheDecorator implements Cache {
|
||||
|
||||
private final Cache targetCache;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new TransactionAwareCache for the given target Cache.
|
||||
* @param targetCache the target Cache to decorate
|
||||
*/
|
||||
public TransactionAwareCacheDecorator(Cache targetCache) {
|
||||
Assert.notNull(targetCache, "Target Cache must not be null");
|
||||
this.targetCache = targetCache;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return this.targetCache.getName();
|
||||
}
|
||||
|
||||
public Object getNativeCache() {
|
||||
return this.targetCache.getNativeCache();
|
||||
}
|
||||
|
||||
public ValueWrapper get(Object key) {
|
||||
return this.targetCache.get(key);
|
||||
}
|
||||
|
||||
public void put(final Object key, final Object value) {
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
targetCache.put(key, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.targetCache.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void evict(final Object key) {
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
targetCache.evict(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.targetCache.evict(key);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.targetCache.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.transaction;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Proxy for a target {@link CacheManager}, exposing transaction-aware {@link Cache} objects
|
||||
* which synchronize their {@link Cache#put} operations with Spring-managed transactions
|
||||
* (through Spring's {@link org.springframework.transaction.support.TransactionSynchronizationManager},
|
||||
* performing the actual cache put operation only in the after-commit phase of a successful transaction.
|
||||
* If no transaction is active, {@link Cache#put} operations will be performed immediately, as usual.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.2
|
||||
* @see #setTargetCacheManager
|
||||
* @see TransactionAwareCacheDecorator
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
*/
|
||||
public class TransactionAwareCacheManagerProxy implements CacheManager, InitializingBean {
|
||||
|
||||
private CacheManager targetCacheManager;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new TransactionAwareCacheManagerProxy, setting the target CacheManager
|
||||
* through the {@link #setTargetCacheManager} bean property.
|
||||
*/
|
||||
public TransactionAwareCacheManagerProxy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TransactionAwareCacheManagerProxy for the given target CacheManager.
|
||||
* @param targetCacheManager the target CacheManager to proxy
|
||||
*/
|
||||
public TransactionAwareCacheManagerProxy(CacheManager targetCacheManager) {
|
||||
Assert.notNull(targetCacheManager, "Target CacheManager must not be null");
|
||||
this.targetCacheManager = targetCacheManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the target CacheManager to proxy.
|
||||
*/
|
||||
public void setTargetCacheManager(CacheManager targetCacheManager) {
|
||||
this.targetCacheManager = targetCacheManager;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
if (this.targetCacheManager == null) {
|
||||
throw new IllegalStateException("'targetCacheManager' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Cache getCache(String name) {
|
||||
return new TransactionAwareCacheDecorator(this.targetCacheManager.getCache(name));
|
||||
}
|
||||
|
||||
public Collection<String> getCacheNames() {
|
||||
return this.targetCacheManager.getCacheNames();
|
||||
}
|
||||
|
||||
}
|
||||
5
spring-context-support/src/main/java/org/springframework/cache/transaction/package-info.java
vendored
Normal file
5
spring-context-support/src/main/java/org/springframework/cache/transaction/package-info.java
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Transaction-aware decorators for the the org.springframework.cache package.
|
||||
* Provides synchronization of put operations with Spring-managed transactions.
|
||||
*/
|
||||
package org.springframework.cache.transaction;
|
||||
Reference in New Issue
Block a user