update simple providers mvc cache annotation spring caching spring-cache

simple - spring mvc cache



Spring cache @Cacheable method ignorado cuando se llama desde dentro de la misma clase (4)

@Cacheable llamar a un método @Cacheable desde dentro de la misma clase:

@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(findPerson(id)); } return list; }

y esperando que los resultados de findPersons estén en caché, pero la anotación @Cacheable se ignora y el método findPerson se ejecuta cada vez.

¿Estoy haciendo algo mal aquí, o esto es intencionado?


Esto es lo que hago para proyectos pequeños con solo el uso marginal de llamadas a métodos dentro de la misma clase. 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, aconsejaría la solución AspectJ.

@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; } }


Esto se debe a la forma en que se crean los proxies para manejar el almacenamiento en caché, la funcionalidad relacionada con la transacción en Spring. Esta es una muy buena referencia de cómo lo maneja Spring: transacciones, almacenamiento en caché y AOP: comprensión del uso del proxy en Spring

En resumen, una auto llamada ignora el proxy dinámico y cualquier preocupación transversal como el almacenamiento en caché, la transacción, etc., que es parte de la lógica dinámica de proxies, también se pasa por alto.

La solución es usar el tiempo de compilación de AspectJ o el tiempo de carga del tejido.


La configuración de la memoria caché interna se puede usar para "proxificar" las llamadas a métodos, vea el ejemplo en esta respuesta: http://.com/a/48168762/907576


Para cualquiera que use el complemento Grails Spring Cache , se describe una solución en la documentación . Tuve este problema en una aplicación de Grails, pero desafortunadamente la respuesta aceptada parece inutilizable para Grails. La solución es fea, en mi humilde opinión, pero funciona.

El código de ejemplo lo demuestra bien:

class ExampleService { def grailsApplication def nonCachedMethod() { grailsApplication.mainContext.exampleService.cachedMethod() } @Cacheable(''cachedMethodCache'') def cachedMethod() { // do some expensive stuff } }

Simplemente reemplace exampleService.cachedMethod () con su propio servicio y método.