From 0d0d7139ee0976e5cacaa4b3d924cfa98e5a2896 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 18 Aug 2014 19:25:40 +0200 Subject: [PATCH] Convenient EhCache CacheManager bootstrapping within @Bean methods Also introducing default CacheManager setup for EhCacheCacheManager, analogous to JCacheCacheManager. Issue: SPR-12093 --- .../cache/ehcache/EhCacheCacheManager.java | 16 ++- .../cache/ehcache/EhCacheFactoryBean.java | 3 +- .../ehcache/EhCacheManagerFactoryBean.java | 66 ++++----- .../cache/ehcache/EhCacheManagerUtils.java | 125 ++++++++++++++++++ 4 files changed, 163 insertions(+), 47 deletions(-) create mode 100644 spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerUtils.java diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java index ec7dabdddc..c5c9f0978f 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java +++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java @@ -69,19 +69,25 @@ public class EhCacheCacheManager extends AbstractTransactionSupportingCacheManag return this.cacheManager; } + @Override + public void afterPropertiesSet() { + if (getCacheManager() == null) { + setCacheManager(EhCacheManagerUtils.buildCacheManager()); + } + super.afterPropertiesSet(); + } + @Override protected Collection loadCaches() { - net.sf.ehcache.CacheManager cacheManager = getCacheManager(); - Assert.notNull(cacheManager, "A backing EhCache CacheManager is required"); - Status status = cacheManager.getStatus(); + Status status = getCacheManager().getStatus(); Assert.isTrue(Status.STATUS_ALIVE.equals(status), "An 'alive' EhCache CacheManager is required - current cache is " + status.toString()); - String[] names = cacheManager.getCacheNames(); + String[] names = getCacheManager().getCacheNames(); Collection caches = new LinkedHashSet(names.length); for (String name : names) { - caches.add(new EhCacheCache(cacheManager.getEhcache(name))); + caches.add(new EhCacheCache(getCacheManager().getEhcache(name))); } return caches; } 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 b4a4ede4c7..eca8be9998 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 @@ -16,7 +16,6 @@ package org.springframework.cache.ehcache; -import java.io.IOException; import java.lang.reflect.Method; import java.util.Set; @@ -231,7 +230,7 @@ public class EhCacheFactoryBean extends CacheConfiguration implements FactoryBea @Override - public void afterPropertiesSet() throws CacheException, IOException { + public void afterPropertiesSet() throws CacheException { // If no cache name given, use bean name as cache name. String cacheName = getName(); if (cacheName == null) { 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 dcc038d6cb..06c5a5e856 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 @@ -16,9 +16,6 @@ package org.springframework.cache.ehcache; -import java.io.IOException; -import java.io.InputStream; - import net.sf.ehcache.CacheException; import net.sf.ehcache.CacheManager; import net.sf.ehcache.config.Configuration; @@ -97,9 +94,6 @@ public class EhCacheManagerFactoryBean implements FactoryBean, Ini * but will simply work with the default CacheManager name if none specified. * All references to the same CacheManager name (or the same default) in the * same ClassLoader space will share the specified CacheManager then. - *

NOTE: This feature requires EhCache 2.5 or higher. In contrast to - * the {@link #setShared "shared"} flag, it supports controlled shutdown of the - * CacheManager by the EhCacheManagerFactoryBean that actually created it. * @see #setCacheManagerName * #see #setShared * @see net.sf.ehcache.CacheManager#getCacheManager(String) @@ -131,44 +125,36 @@ public class EhCacheManagerFactoryBean implements FactoryBean, Ini @Override - public void afterPropertiesSet() throws IOException, CacheException { + public void afterPropertiesSet() throws CacheException { logger.info("Initializing EhCache CacheManager"); - InputStream is = (this.configLocation != null ? this.configLocation.getInputStream() : null); - try { - Configuration configuration = (is != null ? - ConfigurationFactory.parseConfiguration(is) : ConfigurationFactory.parseConfiguration()); - if (this.cacheManagerName != null) { - configuration.setName(this.cacheManagerName); - } - if (this.shared) { - // Old-school EhCache singleton sharing... - // No way to find out whether we actually created a new CacheManager - // or just received an existing singleton reference. - this.cacheManager = CacheManager.create(configuration); - } - else if (this.acceptExisting) { - // EhCache 2.5+: Reusing an existing CacheManager of the same name. - // Basically the same code as in CacheManager.getInstance(String), - // just storing whether we're dealing with an existing instance. - synchronized (CacheManager.class) { - this.cacheManager = CacheManager.getCacheManager(this.cacheManagerName); - if (this.cacheManager == null) { - this.cacheManager = new CacheManager(configuration); - } - else { - this.locallyManaged = false; - } + Configuration configuration = (this.configLocation != null ? + EhCacheManagerUtils.parseConfiguration(this.configLocation) : ConfigurationFactory.parseConfiguration()); + if (this.cacheManagerName != null) { + configuration.setName(this.cacheManagerName); + } + if (this.shared) { + // Old-school EhCache singleton sharing... + // No way to find out whether we actually created a new CacheManager + // or just received an existing singleton reference. + this.cacheManager = CacheManager.create(configuration); + } + else if (this.acceptExisting) { + // EhCache 2.5+: Reusing an existing CacheManager of the same name. + // Basically the same code as in CacheManager.getInstance(String), + // just storing whether we're dealing with an existing instance. + synchronized (CacheManager.class) { + this.cacheManager = CacheManager.getCacheManager(this.cacheManagerName); + if (this.cacheManager == null) { + this.cacheManager = new CacheManager(configuration); + } + else { + this.locallyManaged = false; } } - else { - // Throwing an exception if a CacheManager of the same name exists already... - this.cacheManager = new CacheManager(configuration); - } } - finally { - if (is != null) { - is.close(); - } + else { + // Throwing an exception if a CacheManager of the same name exists already... + this.cacheManager = new CacheManager(configuration); } } diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerUtils.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerUtils.java new file mode 100644 index 0000000000..78f42785d5 --- /dev/null +++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerUtils.java @@ -0,0 +1,125 @@ +/* + * Copyright 2002-2014 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 net.sf.ehcache.config.Configuration; +import net.sf.ehcache.config.ConfigurationFactory; + +import org.springframework.core.io.Resource; + +/** + * Convenient builder methods for EhCache 2.5+ {@link CacheManager} setup, + * providing easy programmatic bootstrapping from a Spring-provided resource. + * This is primarily intended for use within {@code @Bean} methods in a + * Spring configuration class. + * + *

These methods are a simple alternative to custom {@link CacheManager} setup + * code. For any advanced purposes, consider using {@link #parseConfiguration}, + * customizing the configuration object, and then calling the + * {@link CacheManager#CacheManager(Configuration)} constructor. + * + * @author Juergen Hoeller + * @since 4.1 + */ +public abstract class EhCacheManagerUtils { + + /** + * Build an EhCache {@link CacheManager} from the default configuration. + *

The 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). + * If no configuration file can be found, a fail-safe fallback configuration will be used. + * @return the new EhCache CacheManager + * @throws CacheException in case of configuration parsing failure + */ + public static CacheManager buildCacheManager() throws CacheException { + return new CacheManager(ConfigurationFactory.parseConfiguration()); + } + + /** + * Build an EhCache {@link CacheManager} from the default configuration. + *

The 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). + * If no configuration file can be found, a fail-safe fallback configuration will be used. + * @param name the desired name of the cache manager + * @return the new EhCache CacheManager + * @throws CacheException in case of configuration parsing failure + */ + public static CacheManager buildCacheManager(String name) throws CacheException { + Configuration configuration = ConfigurationFactory.parseConfiguration(); + configuration.setName(name); + return new CacheManager(configuration); + } + + /** + * Build an EhCache {@link CacheManager} from the given configuration resource. + * @param configLocation the location of the configuration file (as a Spring resource) + * @return the new EhCache CacheManager + * @throws CacheException in case of configuration parsing failure + */ + public static CacheManager buildCacheManager(Resource configLocation) throws CacheException { + return new CacheManager(parseConfiguration(configLocation)); + } + + /** + * Build an EhCache {@link CacheManager} from the given configuration resource. + * @param name the desired name of the cache manager + * @param configLocation the location of the configuration file (as a Spring resource) + * @return the new EhCache CacheManager + * @throws CacheException in case of configuration parsing failure + */ + public static CacheManager buildCacheManager(String name, Resource configLocation) throws CacheException { + Configuration configuration = parseConfiguration(configLocation); + configuration.setName(name); + return new CacheManager(configuration); + } + + /** + * Parse EhCache configuration from the given resource, for further use with + * custom {@link CacheManager} creation. + * @param configLocation the location of the configuration file (as a Spring resource) + * @return the EhCache Configuration handle + * @throws CacheException in case of configuration parsing failure + * @see CacheManager#CacheManager(Configuration) + * @see CacheManager#create(Configuration) + */ + public static Configuration parseConfiguration(Resource configLocation) throws CacheException { + InputStream is = null; + try { + is = configLocation.getInputStream(); + return ConfigurationFactory.parseConfiguration(is); + } + catch (IOException ex) { + throw new CacheException("Failed to parse EhCache configuration resource", ex); + } + finally { + if (is != null) { + try { + is.close(); + } + catch (IOException ex) { + // ignore + } + } + } + } + +}