example ejemplo data cacheable cache spring caching ehcache

ejemplo - Spring 3.1 @Cacheable-método aún ejecutado



spring cache service (3)

Estoy tratando de implementar el almacenamiento en memoria caché de Spring 3.1 como se explica here y here , pero no parece estar funcionando: mi método se ejecuta a través de todas las veces a pesar de que está marcado @cacheable. ¿Qué estoy haciendo mal?

Lo he trasladado a un caso de prueba junit con su propio archivo de configuración para aislarlo del resto de mi aplicación, pero el problema todavía ocurre. Aquí están los archivos relevantes:

Spring-test-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> <cache:annotation-driven /> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/> <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="classpath:ehcache.xml"/> </beans>

ehcache.xml

<ehcache> <diskStore path="java.io.tmpdir"/> <cache name="cache" maxElementsInMemory="100" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"/> </ehcache>

MyTest.java

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({"classpath:spring-test-servlet.xml"}) @Component public class MyTest extends TestCase { @Test public void testCache1(){ for(int i = 0; i < 5; i++){ System.out.println("Calling someMethod..."); System.out.println(someMethod(0)); } } @Cacheable("testmethod") private int someMethod(int val){ System.out.println("Not from cache"); return 5; } }

Entradas relevantes de Pom: (spring-version = 3.1.1.RELEASE)

<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.5.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency>

cuando ejecuto la prueba, Spring saca algunos mensajes de depuración que parecen que mi caché se inicializó sin errores

DEBUG: config.ConfigurationHelper - No CacheManagerEventListenerFactory class specified. Skipping... DEBUG: ehcache.Cache - No BootstrapCacheLoaderFactory class specified. Skipping... DEBUG: ehcache.Cache - CacheWriter factory not configured. Skipping... DEBUG: config.ConfigurationHelper - No CacheExceptionHandlerFactory class specified. Skipping... DEBUG: store.MemoryStore - Initialized net.sf.ehcache.store.MemoryStore for cache DEBUG: disk.DiskStorageFactory - Failed to delete file cache.data DEBUG: disk.DiskStorageFactory - Failed to delete file cache.index DEBUG: disk.DiskStorageFactory - Matching data file missing (or empty) for index file. Deleting index file /var/folders/qg/xwdvsg6x3mx_z_rcfvq7lc0m0000gn/T/cache.index DEBUG: disk.DiskStorageFactory - Failed to delete file cache.index DEBUG: ehcache.Cache - Initialised cache: cache DEBUG: config.ConfigurationHelper - CacheDecoratorFactory not configured. Skipping for ''cache''. DEBUG: config.ConfigurationHelper - CacheDecoratorFactory not configured for defaultCache. Skipping for ''cache''.

pero el resultado de la depuración no muestra comprobaciones de caché entre las llamadas a métodos de algún Método y la instrucción de impresión desde el interior de algún Método imprime todo el tiempo.

¿Se me escapa algo?


Además de Lee Chee Kiam: Aquí está mi solución para pequeños proyectos con solo el uso marginal de llamadas de método de anulación (no anotadas). El DAO simplemente se inyecta en sí mismo como un proxy y llama a sus propios métodos utilizando ese proxy en lugar de una simple llamada a método. Entonces @Cacheable se considera sin hacer una complicada insturmentación.

La documentación dentro del código es altamente recomendada, ya que puede parecer extraño para los colegas. Pero es fácil de probar, simple, rápido de lograr y me ahorra la instrumentación AspectJ completa. Sin embargo, para un uso más intenso también aconsejaría la solución AspectJ como lo hizo Lee Chee Kiam.

@Service @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) class PersonDao { private final PersonDao _personDao; @Autowired public PersonDao(PersonDao personDao) { _personDao = personDao; } @Cacheable(value = "defaultCache", key = "#id") public Person findPerson(int id) { return getSession().getPerson(id); } public List<Person> findPersons(int[] ids) { List<Person> list = new ArrayList<Person>(); for (int id : ids) { list.add(_personDao.findPerson(id)); } return list; } }


De http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/cache.html

En el modo proxy (que es el predeterminado), solo se interceptan las llamadas a métodos externos que ingresan a través del proxy. Esto significa que la auto invocación, en efecto, un método dentro del objeto objetivo que llama a otro método del objeto objetivo , no conducirá a un almacenamiento en caché real en el tiempo de ejecución incluso si el método invocado está marcado con @Cacheable, considerando usar el modo aspectj en este caso.

y

Visibilidad del método y @Cacheable / @CachePut / @CacheEvict

Al usar proxies, debe aplicar las anotaciones @Cache solo a los métodos con visibilidad pública .

  1. Usted someMethod en el mismo objeto de destino.
  2. Su método @Cacheable no es público.

Debe definir un caché que coincida con el nombre al que hace referencia en su anotación ("método de prueba"). Cree una entrada en su ehcache.xml para ese caché también.