From f2b79c80b03d18d2a7d5767cc3ac482ccfefedd8 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 19 Mar 2013 23:08:05 +0100 Subject: [PATCH] Spring's EhCache setup builds on EhCache 2.1+ now Specifically, EhCacheFactoryBean extends CacheConfiguration now and therefore inherits all configuration properties of the underlying EhCache version. This reduces the need for catching up with new EhCache properties on our side. Issue: SPR-8258 --- .../cache/ehcache/EhCacheFactoryBean.java | 163 ++++-------------- .../ehcache/EhCacheManagerFactoryBean.java | 40 +---- .../cache/ehcache/EhCacheSupportTests.java | 8 +- 3 files changed, 38 insertions(+), 173 deletions(-) diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java index dcec4047ee..435e780e93 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java +++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java @@ -24,20 +24,19 @@ 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.config.CacheConfiguration; 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 @@ -52,8 +51,7 @@ import org.springframework.util.Assert; *

Note: If the named Cache instance is found, the properties will be ignored and the * Cache instance will be retrieved from the CacheManager. * - *

Note: As of Spring 3.0, Spring's EhCache support requires EhCache 1.3 or higher. - * As of Spring 3.2, we recommend using EhCache 2.1 or higher. + *

Note: As of Spring 4.0, Spring's EhCache support requires EhCache 2.1 or higher. * @author Dmitriy Kopylenko * @author Juergen Hoeller @@ -62,36 +60,12 @@ import org.springframework.util.Assert; * @see EhCacheManagerFactoryBean * @see net.sf.ehcache.Cache */ -public class EhCacheFactoryBean implements FactoryBean, BeanNameAware, InitializingBean { +public class EhCacheFactoryBean extends CacheConfiguration implements FactoryBean, 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; @@ -111,6 +85,13 @@ public class EhCacheFactoryBean implements FactoryBean, BeanNameAware, private Ehcache cache; + public EhCacheFactoryBean() { + setMaxElementsInMemory(10000); + setMaxElementsOnDisk(10000000); + setTimeToLiveSeconds(120); + setTimeToIdleSeconds(120); + } + /** * Set a CacheManager from which to retrieve a named Cache instance. * By default, {@code CacheManager.getInstance()} will be called. @@ -131,100 +112,28 @@ public class EhCacheFactoryBean implements FactoryBean, BeanNameAware, * 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. - *

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; + setName(cacheName); } /** - * 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. - *

This is only used if the element is not eternal. Default is 120 seconds. + * @see #setTimeToLiveSeconds(long) */ public void setTimeToLive(int timeToLive) { - this.timeToLive = timeToLive; + setTimeToLiveSeconds(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. - *

This is only used if the element is not eternal. Default is 120 seconds. + * @see #setTimeToIdleSeconds(long) */ 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; + setTimeToIdleSeconds(timeToIdle); } /** - * Set the amount of memory to allocate the write buffer for puts to the disk store. - * Default is 0. + * @see #setDiskSpoolBufferSizeMB(int) */ 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; + setDiskSpoolBufferSizeMB(diskSpoolBufferSize); } /** @@ -303,33 +212,35 @@ public class EhCacheFactoryBean implements FactoryBean, BeanNameAware, public void afterPropertiesSet() throws CacheException, IOException { + // If no cache name given, use bean name as cache name. + String cacheName = getName(); + if (cacheName == null) { + cacheName = this.beanName; + setName(cacheName); + } + // 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 + "'"); + logger.debug("Using default EhCache CacheManager for cache region '" + 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. + // Fetch cache region: If none with the given name exists, create one on the fly. Ehcache rawCache; - if (this.cacheManager.cacheExists(this.cacheName)) { + if (this.cacheManager.cacheExists(cacheName)) { if (logger.isDebugEnabled()) { - logger.debug("Using existing EhCache cache region '" + this.cacheName + "'"); + logger.debug("Using existing EhCache cache region '" + cacheName + "'"); } - rawCache = this.cacheManager.getEhcache(this.cacheName); + rawCache = this.cacheManager.getEhcache(cacheName); } else { if (logger.isDebugEnabled()) { - logger.debug("Creating new EhCache cache region '" + this.cacheName + "'"); + logger.debug("Creating new EhCache cache region '" + cacheName + "'"); } rawCache = createCache(); + rawCache.setBootstrapCacheLoader(this.bootstrapCacheLoader); this.cacheManager.addCache(rawCache); } @@ -360,17 +271,7 @@ public class EhCacheFactoryBean implements FactoryBean, BeanNameAware, * 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); + return new Cache(this); } /** diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java index a94c1fe2cb..ea134b57aa 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java +++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java @@ -18,7 +18,6 @@ package org.springframework.cache.ehcache; import java.io.IOException; import java.io.InputStream; -import java.lang.reflect.Method; import net.sf.ehcache.CacheException; import net.sf.ehcache.CacheManager; @@ -31,8 +30,6 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; /** * {@link FactoryBean} that exposes an EhCache {@link net.sf.ehcache.CacheManager} @@ -47,8 +44,7 @@ import org.springframework.util.ReflectionUtils; * and cares for proper shutdown of the CacheManager. EhCacheManagerFactoryBean is * also necessary for loading EhCache configuration from a non-default config location. * - *

Note: As of Spring 3.0, Spring's EhCache support requires EhCache 1.3 or higher. - * As of Spring 3.2, we recommend using EhCache 2.1 or higher. + *

Note: As of Spring 4.0, Spring's EhCache support requires EhCache 2.1 or higher. * * @author Dmitriy Kopylenko * @author Juergen Hoeller @@ -60,10 +56,6 @@ import org.springframework.util.ReflectionUtils; */ public class EhCacheManagerFactoryBean implements FactoryBean, InitializingBean, DisposableBean { - // Check whether EhCache 2.1+ CacheManager.create(Configuration) method is available... - private static final Method createWithConfiguration = - ClassUtils.getMethodIfAvailable(CacheManager.class, "create", Configuration.class); - protected final Log logger = LogFactory.getLog(getClass()); private Resource configLocation; @@ -110,34 +102,12 @@ public class EhCacheManagerFactoryBean implements FactoryBean, Ini logger.info("Initializing EhCache CacheManager"); InputStream is = (this.configLocation != null ? this.configLocation.getInputStream() : null); try { - // A bit convoluted for EhCache 1.x/2.0 compatibility. - // To be much simpler once we require EhCache 2.1+ + Configuration configuration = (is != null ? + ConfigurationFactory.parseConfiguration(is) : ConfigurationFactory.parseConfiguration()); if (this.cacheManagerName != null) { - if (this.shared && createWithConfiguration == null) { - // No CacheManager.create(Configuration) method available before EhCache 2.1; - // can only set CacheManager name after creation. - this.cacheManager = (is != null ? CacheManager.create(is) : CacheManager.create()); - this.cacheManager.setName(this.cacheManagerName); - } - else { - Configuration configuration = (is != null ? ConfigurationFactory.parseConfiguration(is) : - ConfigurationFactory.parseConfiguration()); - configuration.setName(this.cacheManagerName); - if (this.shared) { - this.cacheManager = (CacheManager) ReflectionUtils.invokeMethod(createWithConfiguration, null, configuration); - } - else { - this.cacheManager = new CacheManager(configuration); - } - } - } - // For strict backwards compatibility: use simplest possible constructors... - else if (this.shared) { - this.cacheManager = (is != null ? CacheManager.create(is) : CacheManager.create()); - } - else { - this.cacheManager = (is != null ? new CacheManager(is) : new CacheManager()); + configuration.setName(this.cacheManagerName); } + this.cacheManager = (this.shared ? CacheManager.create(configuration) : new CacheManager(configuration)); } finally { if (is != null) { diff --git a/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheSupportTests.java b/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheSupportTests.java index 6e8efcd816..492a0f868e 100644 --- a/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheSupportTests.java +++ b/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheSupportTests.java @@ -79,7 +79,7 @@ public class EhCacheSupportTests extends TestCase { } private void doTestEhCacheFactoryBean(boolean useCacheManagerFb) throws Exception { - Cache cache = null; + Cache cache; EhCacheManagerFactoryBean cacheManagerFb = null; try { EhCacheFactoryBean cacheFb = new EhCacheFactoryBean(); @@ -118,11 +118,9 @@ public class EhCacheSupportTests extends TestCase { config = cache.getCacheConfiguration(); assertEquals("undefinedCache", cache.getName()); assertTrue("default maxElements is correct", config.getMaxElementsInMemory() == 10000); - assertTrue("default overflowToDisk is correct", config.isOverflowToDisk()); assertFalse("default eternal is correct", config.isEternal()); assertTrue("default timeToLive is correct", config.getTimeToLiveSeconds() == 120); assertTrue("default timeToIdle is correct", config.getTimeToIdleSeconds() == 120); - assertTrue("default diskPersistent is correct", !config.isDiskPersistent()); assertTrue("default diskExpiryThreadIntervalSeconds is correct", config.getDiskExpiryThreadIntervalSeconds() == 120); // overriding the default properties @@ -132,10 +130,8 @@ public class EhCacheSupportTests extends TestCase { } cacheFb.setBeanName("undefinedCache2"); cacheFb.setMaxElementsInMemory(5); - cacheFb.setOverflowToDisk(false); cacheFb.setTimeToLive(8); cacheFb.setTimeToIdle(7); - cacheFb.setDiskPersistent(true); cacheFb.setDiskExpiryThreadIntervalSeconds(10); cacheFb.afterPropertiesSet(); cache = (Cache) cacheFb.getObject(); @@ -143,10 +139,8 @@ public class EhCacheSupportTests extends TestCase { assertEquals("undefinedCache2", cache.getName()); assertTrue("overridden maxElements is correct", config.getMaxElementsInMemory() == 5); - assertFalse("overridden overflowToDisk is correct", config.isOverflowToDisk()); assertTrue("default timeToLive is correct", config.getTimeToLiveSeconds() == 8); assertTrue("default timeToIdle is correct", config.getTimeToIdleSeconds() == 7); - assertTrue("overridden diskPersistent is correct", config.isDiskPersistent()); assertTrue("overridden diskExpiryThreadIntervalSeconds is correct", config.getDiskExpiryThreadIntervalSeconds() == 10); } finally {