Кеш Spring не работает при вызове кешированного метода из другого метода того же компонента.
Вот пример, ясно объясняющий мою проблему.
Конфигурация:
<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"/>
Кешированный сервис:
@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);
...
}
}
Результат:
aService.getEmployeeData(someDate);
output: Cache is not being used
aService.getEmployeeData(someDate);
output:
aService.getEmployeeEnrichedData(someDate);
output: Cache is not being used
В getEmployeeData
использует вызов метода кэширования employeeData
при втором вызове , как ожидалось. Но когда getEmployeeData
метод вызывается внутри AService
класса (in getEmployeeEnrichedData
), Cache не используется.
Так работает весенний кеш или мне что-то не хватает?
someDate
параметра?Ответы:
Я считаю, что это так. Из того, что я помню, читал, создается прокси-класс, который перехватывает все запросы и отвечает кэшированным значением, но «внутренние» вызовы внутри того же класса не получат кэшированного значения.
Из https://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable
источник
@Cacheable
в DAO :( Если у вас есть лучшее решение, дайте мне знать, спасибо.@Resource
самоавтоматизации, см. Пример stackoverflow.com/a/48867068/907576@Cacheable
должен быть внешний методpublic
, он не работает с частными методами пакета. Нашел трудный путь.Начиная с Spring 4.3 проблема может быть решена с помощью автоматического подключения к
@Resource
аннотации:источник
4.3.17
и это не сработало, призывыself
не проходить через прокси, а кеш (все еще) обходится.Пример ниже - это то, что я использую для обращения к прокси из одного и того же bean-компонента, он похож на решение @ mario-eis, но я считаю его более читаемым (возможно, это не так :-). Во всяком случае, мне нравится сохранять аннотации @Cacheable на уровне обслуживания:
См. Также Запуск новой транзакции в Spring bean
источник
applicationContext.getBean(SettingService.class);
, доступ к контексту приложения противоположен внедрению зависимости. Я предлагаю избегать этого стиля.Вот что я делаю для небольших проектов с минимальным использованием вызовов методов в одном классе. Настоятельно рекомендуется внутренняя документация, поскольку она может показаться коллегам странной. Но его легко протестировать, просто, быстро реализовать и избавить меня от полноценного инструментария AspectJ. Однако для более интенсивного использования я бы посоветовал решение AspectJ.
источник
В моем случае я добавляю переменную:
Поэтому я вызываю
getEmployeeData
метод, используяaService
}
В этом случае он будет использовать кеш.
источник
Используйте статическое плетение для создания прокси вокруг вашего bean-компонента. В этом случае корректно работали бы даже «внутренние» методы.
источник
<iajc
компилятор (от ant), который решает все аспекты необходимости для классов с возможностью кеширования.FactoryInternalCache
Для этой цели я использую внутренний внутренний bean ( ) с реальным кешем:источник
самое простое решение - просто сослаться на это:
источник