O cache do Spring não está funcionando ao chamar o método em cache de outro método do mesmo bean.
Aqui está um exemplo para explicar meu problema de forma clara.
Configuração:
<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"/>
Serviço em cache:
@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
A getEmployeeData
chamada do método usa cache employeeData
na segunda chamada conforme o esperado. Mas quando o getEmployeeData
método é chamado dentro da AService
classe (in getEmployeeEnrichedData
), o Cache não está sendo usado.
É assim que o Spring Cache funciona ou estou faltando alguma coisa?
someDate
param?Respostas:
Eu acredito que é assim que funciona. Pelo que me lembro de ter lido, há uma classe de proxy gerada que intercepta todas as solicitações e responde com o valor armazenado em cache, mas chamadas 'internas' dentro da mesma classe não obterão o valor armazenado em cache.
De https://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable
fonte
@Cacheable
para o DAO :( Se você tiver uma solução melhor, por favor, me avise, obrigado.@Resource
self-autowiring, veja o exemplo stackoverflow.com/a/48867068/907576@Cacheable
método externo deve serpublic
, ele não funciona em métodos privados de pacote. Achei da maneira mais difícil.Desde o Spring 4.3, o problema pode ser resolvido usando self-autowiring sobre
@Resource
anotação:fonte
4.3.17
e não funcionou, chamadas paraself
não passarem por um proxy e o cache (ainda) é ignorado.O exemplo abaixo é o que eu uso para acessar o proxy de dentro do mesmo bean, é semelhante à solução de @ mario-eis, mas acho que é um pouco mais legível (talvez não seja :-). De qualquer forma, gosto de manter as anotações @Cacheable no nível de serviço:
Veja também Iniciando uma nova transação no Spring bean
fonte
applicationContext.getBean(SettingService.class);
, é o oposto da injeção de dependência. Eu sugiro evitar esse estilo.Aqui está o que eu faço para pequenos projetos com uso apenas marginal de chamadas de método dentro da mesma classe. A documentação in-code é fortemente recomendada, pois pode parecer difícil para os colegas. Mas é fácil de testar, simples, rápido de conseguir e me poupa da instrumentação AspectJ completa. No entanto, para um uso mais intenso, aconselho a solução AspectJ.
fonte
No meu caso, adiciono a variável:
Então, chamo o
getEmployeeData
método usando oaService
}
Ele usará o cache neste caso.
fonte
Use a tecelagem estática para criar proxy em torno de seu bean. Neste caso, mesmo os métodos "internos" funcionariam corretamente
fonte
<iajc
compilador (da Ant) que resolve todos os aspectos de necessidade para classes com capacidade de cache.Eu uso o bean interno interno (
FactoryInternalCache
) com cache real para esta finalidade:fonte
a solução mais fácil, de longe, é apenas fazer referência a esta:
fonte