SimpleCacheManager
на SimpleCacheManager
, который, по словам парней в Spring, «полезен для тестирования или простых объявлений кэширования». Я на самом деле предпочитаю думать о SimpleCacheManager
как о легком, а не простом; полезно в тех ситуациях, когда требуется небольшой кэш-память для каждой виртуальной машины Java. Если бы «Ребята в Spring» управляли супермаркетом, то SimpleCacheManager
был бы в линейке продуктов «Основы» своего бренда.
Если, с другой стороны, вам нужен мощный кэш, который можно масштабировать, сохранять и распределять, тогда Spring также поставляется со встроенной оболочкой ehCache .
Хорошая новость заключается в том, что переключаться между реализациями Spring в кэшировании легко. Теоретически все зависит от конфигурации, и, чтобы доказать правильность теории, я взял пример кода из своего блога Caching и @Cacheable
и запустил его с помощью реализации EhCache.
Этапы настройки аналогичны описанным в моем последнем блоге Caching and Config , но вам все равно нужно указать:
1
|
< cache:annotation-driven /> |
… В вашем конфигурационном файле Spring для включения кэширования. Вам также нужно определить бин с идентификатором cacheManager
, только в этот раз вы ссылаетесь на класс Spring EhCacheCacheManager
вместо SimpleCacheManager
.
1
2
3
|
< bean id = 'cacheManager' class = 'org.springframework.cache.ehcache.EhCacheCacheManager' p:cacheManager-ref = 'ehcache' /> |
В приведенном выше примере демонстрируется конфигурация EhCacheCacheManager
. Обратите внимание, что он ссылается на второй компонент с идентификатором « ehcache
». Это настроено следующим образом:
1
2
3
|
< bean id = 'ehcache' class = 'org.springframework.cache.ehcache.EhCacheManagerFactoryBean' p:configLocation = 'ehcache.xml' p:shared = 'true' /> |
« ehcache
» имеет два свойства: configLocation
и shared
.
‘ configLocation
‘ — это необязательный атрибут, который используется для указания местоположения файла конфигурации ehcache. В моем тестовом коде я использовал следующий файл примера:
1
2
3
4
5
|
<? 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 > |
… Который создает два кэша: кэш по умолчанию и один с именем «employee».
Если этот файл отсутствует, EhCacheManagerFactoryBean
просто выбирает файл конфигурации ehcache по умолчанию: ehcache-failsafe.xml
, который находится в jar-файле ehcache-core
.
EhCacheManagerFactoryBean
атрибут EhCacheManagerFactoryBean
является « shared
». Предполагается, что это необязательно, поскольку в документации указывается, что она определяет, «должен ли EHCache CacheManager использоваться совместно (как единое целое на уровне виртуальной машины) или быть независимым (обычно локальным в приложении). По умолчанию установлено значение «false», что создает независимый экземпляр ». Однако, если для этого параметра установлено значение false, вы получите следующее исключение:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
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 clarity at 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 clarity at 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 работает нормально, но все остальные не пройдены.
Обидная строка кода:
1
|
this .cacheManager = ( this .shared ? CacheManager.create() : new CacheManager()); |
Мой полный XML-файл конфигурации приведен ниже для полноты:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<? xml version = '1.0' encoding = 'UTF-8' ?> xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://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 в один модуль Maven POM . Этот модуль POM может быть добавлен в файл POM вашего проекта с использованием приведенного ниже XML:
1
2
3
4
5
6
7
|
< dependency > < groupId >net.sf.ehcache</ groupId > < artifactId >ehcache</ artifactId > < version >2.6.0</ version > < type >pom</ type > < scope >test</ scope > </ dependency > |
Наконец, файлы Jar ehcache доступны как из репозиториев Maven Central, так и из Sourceforge:
01
02
03
04
05
06
07
08
09
10
11
12
|
< repositories > < repository > < id >sourceforge</ id > < releases > < enabled >true</ enabled > </ releases > < snapshots > < enabled >true</ enabled > </ snapshots > </ repository > </ repositories > |
Приятного кодирования и не забудьте поделиться!
Ссылка: Spring 3.1: Caching и EhCache от нашего партнера по JCG Роджера Хьюза в блоге Captain Debug’s Blog .