我有一个util模块,可以生成一个可以在其他应用程序中使用的jar。我希望这个模块使用缓存,并且更喜欢使用Spring的annotation-driven
缓存。
所以Util-Module
会有这样的事情:
DataManager.java
...
@Cacheable(cacheName="getDataCache")
public DataObject getData(String key) { ... }
...
数据的管理器-ehcache.xml中
...
<cache name="getDataCache" maxElementsInMemory="100" eternal="true" />
...
数据的管理器 - 弹簧 - config.xml中
...
<cache:annotation-driven cache-manager="data-manager-cacheManager" />
<!-- ???? --->
<bean id="data-manager-cacheManager"
class="org.springframework.cache.ehcache.EhcacheCacheManager"
p:cache-manager="data-manager-ehcache"/>
<bean id="data-manager-ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="data-manager-ehcache.xml"/>
...
我还希望我的可部署单元通过Spring注释进行缓存,同时将上面的jar包含为依赖项。所以我的Deployable-Unit
会有类似的东西:
MyApp.java
...
@Cacheable(cacheName="getMyAppObjectCache")
public MyAppObject getMyAppObject(String key) { ... }
...
我-APP-ehcache.xml中
...
<cache name="getMyAppObjectCache" maxElementsInMemory="100" eternal="true" />
...
我应用内弹簧-config.xml中
...
<cache:annotation-driven cache-manager="my-app-cacheManager" />
<!-- ???? --->
<bean id="my-app-cacheManager"
class="org.springframework.cache.ehcache.EhcacheCacheManager"
p:cache-manager="my-app-ehcache"/>
<bean id="my-app-ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="my-app-ehcache.xml"/>
...
是否可以在主项目和依赖模块中使用注释驱动的缓存,同时保持配置分离?
如果没有,将会理解为什么不是这样的解释。如果是这样,将理解上述配置中需要改变的内容的解释。
答案 0 :(得分:13)
<cache:annotation-driven cache-manager="cacheManager" />
<bean id="cacheManager" class="org.springframework.cache.support.CompositeCacheManager">
<property name="cacheManagers">
<array>
<ref bean="cacheManager1" />
<ref bean="cacheManager2" />
</array>
</property>
<property name="addNoOpCache" value="true" />
</bean>
答案 1 :(得分:9)
这似乎在3.2M1中已修复,请参阅https://jira.springsource.org/browse/SPR-8696
答案 2 :(得分:5)
Spring目前期望cacheManager是Singleton。这是ehcache-spring-annotations项目遇到的问题,我还没有看到请求得到满足。 http://code.google.com/p/ehcache-spring-annotations/issues/detail?id=76
与Java和Spring一样,您可以选择重新实现该类。
http://forums.terracotta.org/forums/posts/list/5618.page#27960提供了一些基础解释,说明了某些人提出的解决方法和
他们想出的实际代码是什么。该方法确实创建了一个遵循的约定,但如果您不喜欢所描述的实际方法,则可以使用您自己的版本重新实现它。
答案 3 :(得分:2)
在我的项目中,我一直在 XYZ war 中使用 ABC jar ,两者都使用Spring 3.1实现 ehCache,xml驱动配置(我们有ehCache.xml,然后是spring-context.xml,我们在两个项目中通过Spring AOP拦截缓存。我们收到了以下错误:
java.lang.IllegalArgumentException: Cannot find cache named [xxxxxx] for CacheableOperation[] caches=[Cxxxxxxxx] | condition='' | key='#xxxxxxxxxxxxx'
at org.springframework.cache.interceptor.CacheAspectSupport.getCaches(CacheAspectSupport.java:163) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.<init>(CacheAspectSupport.java:443) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.getOperationContext(CacheAspectSupport.java:173) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.createOperationContext(CacheAspectSupport.java:404) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:192) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:66) [spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at com.infy.flypp.dao.ContentDAO$$EnhancerByCGLIB$$9443481.getContentById(<generated>) [cglib-2.2.2.jar:]
<强>解决方案:强>
这就是我们解决这个问题的方法:
ABCehCache.xml
(从ABC jar)复制到XYZehCache.xml
(来自XYZ战争)。ABCehCache.xml
(来自ABC jar),但ehCache.xml
内的所有配置(如ABC-spring.xml
和Spring AOP的bean实例化)都将保持不变。XYZ-spring.xml
中,我们导入了ABC-spring.xml
并定义了复合缓存管理器。支持的配置文件:
<强> ABC-spring.xml:强>
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="CacheManager1" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache"></property>
</bean>
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="classpath:ABCEhcache.xml" />
<强> XYZ-spring.xml:强>
<import resource="classpath*:ABC-spring.xml" />
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="cacheManager" class="org.springframework.cache.support.CompositeCacheManager">
<property name="cacheManagers">
<array>
<ref bean="CacheManager1" />
<ref bean="CacheManager2" />
</array>
</property>
<property name="fallbackToNoOpCache" value="true" />
</bean>
<bean id="CacheManager2" class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cache-manager-ref="ehcache" />
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="classpath:XYZEhcache.xml" />
答案 4 :(得分:1)
我会考虑以下更简单的替代方案:
我不喜欢 CompositeCacheManager 的解决方案,因为它的行为非常依赖于底层缓存的实现:只有当所有底层缓存管理器在未知缓存名称上返回null时,它才会按预期工作。有些实现会动态创建它们,从而产生具有您不期望的配置的缓存。