Le cache Spring ne fonctionne pas lors de l'appel d'une méthode mise en cache à partir d'une autre méthode du même bean.
Voici un exemple pour expliquer mon problème de manière claire.
Configuration:
<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"/>
Service mis en 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);
...
}
}
Résultat :
aService.getEmployeeData(someDate);
output: Cache is not being used
aService.getEmployeeData(someDate);
output:
aService.getEmployeeEnrichedData(someDate);
output: Cache is not being used
L' getEmployeeData
appel de méthode utilise le cache employeeData
dans le deuxième appel comme prévu. Mais lorsque la getEmployeeData
méthode est appelée dans la AService
classe (in getEmployeeEnrichedData
), Cache n'est pas utilisé.
Est-ce ainsi que fonctionne Spring Cache ou est-ce que je manque quelque chose?
someDate
param?Réponses:
Je crois que c'est ainsi que cela fonctionne. D'après ce que je me souviens avoir lu, il existe une classe proxy générée qui intercepte toutes les demandes et répond avec la valeur mise en cache, mais les appels «internes» au sein de la même classe n'obtiendront pas la valeur mise en cache.
Depuis https://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable
la source
@Cacheable
à DAO: (Si vous avez une meilleure solution, faites-le moi savoir, merci.@Resource
auto-câblage, voir l'exemple stackoverflow.com/a/48867068/907576@Cacheable
méthode externe devrait l'êtrepublic
, elle ne fonctionne pas sur les méthodes privées de package. Je l'ai trouvé à la dure.Depuis le printemps 4.3, le problème peut être résolu en utilisant l' auto-autowiring sur l'
@Resource
annotation:la source
4.3.17
et cela n'a pas fonctionné, les appels pourself
ne pas passer par un proxy et le cache est (toujours) contourné.L'exemple ci-dessous est ce que j'utilise pour frapper le proxy depuis le même bean, il est similaire à la solution de @ mario-eis, mais je le trouve un peu plus lisible (peut-être que ce n'est pas :-). Quoi qu'il en soit, j'aime garder les annotations @Cacheable au niveau du service:
Voir aussi Démarrer une nouvelle transaction dans Spring Bean
la source
applicationContext.getBean(SettingService.class);
, est l'opposé de l'injection de dépendances. Je suggère d'éviter ce style.Voici ce que je fais pour les petits projets avec une utilisation marginale des appels de méthode dans la même classe. La documentation dans le code est fortement conseillée, car elle peut sembler stridente aux collègues. Mais c'est facile à tester, simple, rapide à réaliser et m'épargne l'instrumentation AspectJ à part entière. Cependant, pour une utilisation plus intensive, je conseillerais la solution AspectJ.
la source
Dans mon cas, j'ajoute une variable:
J'appelle donc la
getEmployeeData
méthode en utilisant leaService
}
Il utilisera le cache dans ce cas.
la source
Utilisez le tissage statique pour créer un proxy autour de votre bean. Dans ce cas, même les méthodes `` internes '' fonctionneraient correctement
la source
<iajc
compilateur (de ant) qui résout tous les aspects de nécessité pour les classes pouvant être mises en cache.J'utilise le bean interne interne (
FactoryInternalCache
) avec un vrai cache à cet effet:la source
la solution la plus simple est de loin de faire référence comme ceci:
la source