providers implementations ejemplo cacheevict cacheable cache spring caching annotations ehcache spring-annotations

implementations - Usar la anotación de Spring cache en múltiples módulos



spring cache ttl (5)

Consideraría las siguientes alternativas mucho más simples:

  1. Opción 1: Anote sus métodos almacenables en caché en el módulo de utilidad con @Cacheable, pero deje que la aplicación adjuntada cree y configure los cachés. En su ejemplo, declararía y configuraría un caché ''getDataCache'' en el módulo de la aplicación, aunque el caché se utiliza en anotaciones para una clase que reside en el módulo de utilidad.
  2. Opción 2: dejar que el módulo de utilidad cree la configuración de caché, pero no el administrador de caché. El módulo de aplicación combinaría las configuraciones de caché de los módulos de utilidad y la aplicación en sí para crear un único administrador de caché.

No me gustó la solución de CompositeCacheManager , ya que su comportamiento depende mucho de la implementación de cachés subyacentes: solo funcionará como se espera si todos los administradores de caché subyacentes devuelven nulo el nombre de caché desconocido. Algunas implementaciones las crearían sobre la marcha, lo que generaría cachés con configuraciones que no esperabas.

Tengo un módulo de utilidad que produce un jar para usar en otras aplicaciones. Me gustaría que este módulo use el almacenamiento en caché y preferiría utilizar el almacenamiento en memoria caché annotation-driven de Spring.

Entonces, Util-Module tendría algo como esto:

DataManager.java

... @Cacheable(cacheName="getDataCache") public DataObject getData(String key) { ... } ...

data-manager-ehcache.xml

... <cache name="getDataCache" maxElementsInMemory="100" eternal="true" /> ...

data-manager-spring-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"/> ...

También me gustaría que mi unidad desplegable tenga almacenamiento en caché a través de la anotación Spring, mientras que incluye el contenedor anterior como una dependencia. Entonces mi Deployable-Unit tendría algo como esto:

MyApp.java

... @Cacheable(cacheName="getMyAppObjectCache") public MyAppObject getMyAppObject(String key) { ... } ...

my-app-ehcache.xml

... <cache name="getMyAppObjectCache" maxElementsInMemory="100" eternal="true" /> ...

my-app-spring-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"/> ...

Pregunta:

¿Es posible utilizar el almacenamiento en memoria caché dirigido por anotación tanto en su proyecto principal como en un módulo de dependencia, manteniendo las configuraciones separadas?

De lo contrario, se agradecería una explicación de por qué no lo es. De ser así, se agradecería una explicación de lo que debe cambiar en la configuración anterior.


En mi proyecto he estado utilizando el contenedor ABC dentro de XYZ war , implementando ehCache con Spring 3.1, configuración basada en xml (tenemos ehCache.xml y luego spring-context.xml donde estamos interceptando el caché mediante Spring AOP en ambos proyectos) . Y estamos obteniendo el siguiente error:

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:]

Solución:

Así es como resolvimos este problema:

  1. ABCehCache.xml toda la configuración de la memoria caché de ABCehCache.xml (de ABC jar) a XYZehCache.xml (de XYZ war).
  2. ABCehCache.xml el ABCehCache.xml (del ABCehCache.xml ABC) pero toda la configuración (como la ehCache.xml instancias de bean para ehCache.xml y Spring AOP) dentro de ABC-spring.xml seguirá siendo la misma.
  3. En XYZ-spring.xml , XYZ-spring.xml ABC-spring.xml y definimos el administrador de caché compuesto.

Archivos de configuración admitidos:

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" />


Spring actualmente espera que el cacheManager sea Singleton. Esto es algo con lo que se encontró el proyecto ehcache-spring-annotations y todavía no he visto la solicitud cumplida. http://code.google.com/p/ehcache-spring-annotations/issues/detail?id=76

Como con todas las cosas de Java y Spring, tienes la opción de volver a implementar la clase.

http://forums.terracotta.org/forums/posts/list/5618.page#27960 proporciona una explicación básica de lo que algunas personas han encontrado como una solución y

Es el código real que se les ocurrió. El enfoque crea una convención a seguir, pero sería bastante fácil volver a implementar esto con su propia versión si no le gusta el enfoque real descrito.