Spring cache no funciona cuando se llama al método en caché desde otro método del mismo bean.
Aquí hay un ejemplo para explicar mi problema de manera clara.
Configuración:
<cache:annotation-driven cache-manager="myCacheManager" />
<bean id="myCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="myCache" />
</bean>
<!-- Ehcache library setup -->
<bean id="myCache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:shared="true">
<property name="configLocation" value="classpath:ehcache.xml"></property>
</bean>
<cache name="employeeData" maxElementsInMemory="100"/>
Servicio en caché:
@Named("aService")
public class AService {
@Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
..println("Cache is not being used");
...
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = getEmployeeData(date);
...
}
}
Resultado:
aService.getEmployeeData(someDate);
output: Cache is not being used
aService.getEmployeeData(someDate);
output:
aService.getEmployeeEnrichedData(someDate);
output: Cache is not being used
La getEmployeeData
llamada al método usa caché employeeData
en la segunda llamada como se esperaba. Pero cuando getEmployeeData
se llama al método dentro de la AService
clase (in getEmployeeEnrichedData
), Cache no se utiliza.
¿Es así como funciona Spring Caché o me falta algo?
someDate
param?Respuestas:
Creo que así es como funciona. Por lo que recuerdo haber leído, hay una clase de proxy generada que intercepta todas las solicitudes y responde con el valor en caché, pero las llamadas 'internas' dentro de la misma clase no obtendrán el valor en caché.
De https://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable
fuente
@Cacheable
a DAO :( Si tiene una mejor solución, hágamelo saber, gracias.@Resource
auto-cableado automático, vea el ejemplo stackoverflow.com/a/48867068/907576@Cacheable
método externo debería serpublic
, no funciona en métodos privados de paquetes. Lo encontré de la manera más difícil.Desde Spring 4.3, el problema podría resolverse utilizando autoajuste sobre
@Resource
anotación:fuente
4.3.17
y no funcionó, las llamadasself
no pasan por un proxy y la caché (aún) se omite.El siguiente ejemplo es lo que utilizo para acceder al proxy desde el mismo bean, es similar a la solución de @ mario-eis, pero la encuentro un poco más legible (tal vez no lo sea :-). De todos modos, me gusta mantener las anotaciones @Cacheable en el nivel de servicio:
Consulte también Iniciar una nueva transacción en Spring bean
fuente
applicationContext.getBean(SettingService.class);
, es lo opuesto a la inyección de dependencia. Sugiero evitar ese estilo.Esto es lo que hago para proyectos pequeños con un uso marginal de llamadas a métodos dentro de la misma clase. Se recomienda encarecidamente la documentación en código, 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 completa de AspectJ. Sin embargo, para un uso más intenso, recomendaría la solución AspectJ.
fuente
En mi caso agrego variable:
Entonces llamo al
getEmployeeData
método usando elaService
}
Utilizará el caché en este caso.
fuente
Utilice tejido estático para crear un proxy alrededor de su frijol. En este caso, incluso los métodos 'internos' funcionarían correctamente
fuente
<iajc
compilador (de ant) que resuelve todos los aspectos de necesidad para las clases que se pueden almacenar en caché.Utilizo el bean interno interno (
FactoryInternalCache
) con caché real para este propósito:fuente
la solución más fácil de lejos es simplemente hacer referencia a esto:
fuente