SimpleCacheManager
,Spring的家伙說這對“用于測試或簡單的緩存聲明很有用”。 實際上,我更喜歡將SimpleCacheManager
看作是輕量級的,而不是簡單的。 在您希望每個JVM占用少量內存緩存的情況下很有用。 如果Spring的家伙正在經營一家超市,那么SimpleCacheManager
將屬于他們自己品牌的“基本”產品范圍。 另一方面,如果您需要一個可擴展,持久和分布式的重型緩存,則Spring還附帶內置的ehCache包裝器。
好消息是,Spring的緩存實現之間的交換很容易。 從理論上講,這完全是配置問題,為了證明該理論正確,我從Caching和@Cacheable
博客中獲取了示例代碼,并使用EhCache實現對其進行了運行。
配置步驟與我上一篇博客“ 緩存和配置”中描述的步驟相似,您仍然需要指定:
<cache:annotation-driven />
…在您的Spring配置文件中以打開緩存。 您還需要定義一個id為cacheManager
的bean,只是這一次您引用Spring的EhCacheCacheManager
類而不是SimpleCacheManager
。
<bean id='cacheManager'class='org.springframework.cache.ehcache.EhCacheCacheManager'p:cacheManager-ref='ehcache'/>
上面的示例演示了EhCacheCacheManager
配置。 注意,它引用了另一個ID為“ ehcache
”的bean。 配置如下:
<bean id='ehcache' class='org.springframework.cache.ehcache.EhCacheManagerFactoryBean'p:configLocation='ehcache.xml'p:shared='true'/>
“ ehcache
”具有兩個屬性: configLocation
和shared
。
“ configLocation
”是一個可選屬性,用于指定ehcache配置文件的位置。 在測試代??碼中,我使用了以下示例文件:
<?xml version='1.0' encoding='UTF-8'?>
<ehcache xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:noNamespaceSchemaLocation='http://ehcache.org/ehcache.xsd'><defaultCache eternal='true' maxElementsInMemory='100' overflowToDisk='false' /><cache name='employee' maxElementsInMemory='10000' eternal='true' overflowToDisk='false' />
</ehcache>
…這將創建兩個緩存:一個默認緩存和一個名為“員工”的緩存。
如果缺少此文件,則EhCacheManagerFactoryBean
只需選擇一個默認的ehcache配置文件: ehcache-failsafe.xml
,該文件位于ehcache的ehcache-core
jar文件中。
另一個EhCacheManagerFactoryBean
屬性是' shared
'。 這被認為是可選的,因為文檔指出它定義了“ EHCache CacheManager是應該共享(作為VM級別的單例)還是獨立的(通常在應用程序內部)。 默認值為'false',創建一個獨立的實例。” 但是,如果將其設置為false,則將收到以下異常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cache.interceptor.CacheInterceptor#0': Cannot resolve reference to bean 'cacheManager' while setting bean property 'cacheManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheManager' defined in class path resource [ehcache-example.xml]: Cannot resolve reference to bean 'ehcache' while setting bean property 'cacheManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ehcache' defined in class path resource [ehcache-example.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.
The source of the existing CacheManager is: InputStreamConfigurationSource [stream=java.io.BufferedInputStream@424c414]at org.springframework.beans.factory.support.BeanDefinitionValueResolver.
resolveReference(BeanDefinitionValueResolver.java:328)at org.springframework.beans.factory.support.BeanDefinitionValueResolver.
resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
populateBean(AbstractAutowireCapableBeanFactory.java:1118)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
doCreateBean(AbstractAutowireCapableBeanFactory.java:517)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
createBean(AbstractAutowireCapableBeanFactory.java:456)
... stack trace shortened for clarityat org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.
java:683)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.
run(RemoteTestRunner.java:390)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.
main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheManager' defined in class path resource [ehcache-example.xml]: Cannot resolve reference to bean 'ehcache' while setting bean property 'cacheManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ehcache' defined in class path resource [ehcache-example.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.
The source of the existing CacheManager is: InputStreamConfigurationSource [stream=java.io.BufferedInputStream@424c414]at org.springframework.beans.factory.support.BeanDefinitionValueResolver.
resolveReference(BeanDefinitionValueResolver.java:328)at org.springframework.beans.factory.support.BeanDefinitionValueResolver.
resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
... stack trace shortened for clarityat org.springframework.beans.factory.support.AbstractBeanFactory.
getBean(AbstractBeanFactory.java:193)at org.springframework.beans.factory.support.BeanDefinitionValueResolver.
resolveReference(BeanDefinitionValueResolver.java:322)... 38 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ehcache' defined in class path resource [ehcache-example.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.
The source of the existing CacheManager is: InputStreamConfigurationSource [stream=java.io.BufferedInputStream@424c414]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
initializeBean(AbstractAutowireCapableBeanFactory.java:1455)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
doCreateBean(AbstractAutowireCapableBeanFactory.java:519)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
createBean(AbstractAutowireCapableBeanFactory.java:456)at org.springframework.beans.factory.support.AbstractBeanFactory$1
.getObject(AbstractBeanFactory.java:294)at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.
getSingleton(DefaultSingletonBeanRegistry.java:225)at org.springframework.beans.factory.support.AbstractBeanFactory.
doGetBean(AbstractBeanFactory.java:291)at org.springframework.beans.factory.support.AbstractBeanFactory.
getBean(AbstractBeanFactory.java:193)at org.springframework.beans.factory.support.BeanDefinitionValueResolver.
resolveReference(BeanDefinitionValueResolver.java:322)... 48 more
Caused by: net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.
The source of the existing CacheManager is: InputStreamConfigurationSource [stream=java.io.BufferedInputStream@424c414]at net.sf.ehcache.CacheManager.assertNoCacheManagerExistsWithSameName(CacheManager.
java:521)at net.sf.ehcache.CacheManager.init(CacheManager.java:371)at net.sf.ehcache.CacheManager.(CacheManager.java:339)at org.springframework.cache.ehcache.EhCacheManagerFactoryBean.
afterPropertiesSet(EhCacheManagerFactoryBean.java:104)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
initializeBean(AbstractAutowireCapableBeanFactory.java:1452)... 55 more
…當您嘗試運行一系列單元測試時。
我認為這歸結為Spring的ehcache管理器工廠的一個簡單錯誤,因為它試圖使用new()
創建多個緩存實例,而不是使用“其中一種CacheManager.create()靜態工廠方法”作為例外,允許其重用相同名稱的相同CacheManager。 因此,我的第一個JUnit測試工作正常,但其他所有測試均失敗。

令人反感的代碼行是:
this.cacheManager = (this.shared ? CacheManager.create() : new CacheManager());
為了完整性,下面列出了我的完整XML配置文件:
<?xml version='1.0' encoding='UTF-8'?>
<beans xmlns='http://www.springframework.org/schema/beans' xmlns:p='http://www.springframework.org/schema/p'xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'xmlns:cache='http://www.springframework.org/schema/cache' xmlns:context='http://www.springframework.org/schema/context'xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsdhttp://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd'><!-- Switch on the Caching --><cache:annotation-driven /><!-- Do the component scan path --><context:component-scan base-package='caching' /><bean id='cacheManager' class='org.springframework.cache.ehcache.EhCacheCacheManager' p:cacheManager-ref='ehcache'/><bean id='ehcache' class='org.springframework.cache.ehcache.EhCacheManagerFactoryBean' p:configLocation='ehcache.xml' p:shared='true'/>
</beans>
在使用ehcache時,要考慮的唯一其他配置詳細信息是Maven依賴項。 這些非常簡單,因為Ehcache的專家們將所有各種ehcache jar組合到一個Maven POM模塊中。 可以使用下面的XML將該POM模塊添加到項目的POM文件中:
<dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId><version>2.6.0</version><type>pom</type><scope>test</scope></dependency>
最后,可以從Maven Central和Sourceforge存儲庫中獲得ehcache Jar文件:
<repositories><repository><id>sourceforge</id><url>http://oss.sonatype.org/content/groups/sourceforge/</url><releases><enabled>true</enabled></releases><snapshots><enabled>true</enabled></snapshots></repository></repositories>
祝您編程愉快,別忘了分享!
參考: Spring 3.1:來自Captain Debug's Blog博客的JCG合作伙伴 Roger Hughes的緩存和EhCache 。
翻譯自: https://www.javacodegeeks.com/2012/10/spring-31-caching-and-ehcache.html