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.