Spring cache nie działa podczas wywoływania metody buforowanej z innej metody tego samego beana.
Oto przykład, który wyjaśnia mój problem w jasny sposób.
Konfiguracja:
<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"/>
Usługa buforowana:
@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);
...
}
}
Wynik:
aService.getEmployeeData(someDate);
output: Cache is not being used
aService.getEmployeeData(someDate);
output:
aService.getEmployeeEnrichedData(someDate);
output: Cache is not being used
Do getEmployeeData
zastosowania metody połączeń buforować employeeData
w drugim naborze, jak oczekiwano. Ale gdy getEmployeeData
metoda jest wywoływana w AService
klasie (in getEmployeeEnrichedData
), pamięć podręczna nie jest używana.
Czy tak działa Spring Cache, czy czegoś mi brakuje?
someDate
parametru?Odpowiedzi:
Wierzę, że tak to działa. Z tego, co pamiętam, czytałem, że jest wygenerowana klasa proxy, która przechwytuje wszystkie żądania i odpowiada za pomocą wartości z pamięci podręcznej, ale wywołania „wewnętrzne” w ramach tej samej klasy nie otrzymają wartości z pamięci podręcznej.
Od https://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable
źródło
@Cacheable
na DAO :( Jeśli masz lepsze rozwiązanie, daj mi znać, dzięki.@Resource
samoczynnego okablowania, patrz przykład stackoverflow.com/a/48867068/907576@Cacheable
Powinna być również metoda zewnętrznapublic
, która nie działa z metodami prywatnymi pakietu. Znalazłem to na własnej skórze.Od wiosny 4.3 problem można rozwiązać za pomocą samoczynnego okablowania nad
@Resource
adnotacją:źródło
4.3.17
i to nie zadziałało, wywołaniaself
nie przechodzą przez proxy, a pamięć podręczna jest (nadal) pomijana.Poniższy przykład jest tym, czego używam, aby trafić do proxy z tego samego ziarna, jest podobny do rozwiązania @ mario-eis, ale uważam, że jest nieco bardziej czytelny (może nie jest :-). W każdym razie lubię utrzymywać adnotacje @Cacheable na poziomie usług:
Zobacz także Rozpoczynanie nowej transakcji w ziarnie wiosennym
źródło
applicationContext.getBean(SettingService.class);
jest na przykład przeciwieństwem wstrzykiwania zależności. Proponuję unikać tego stylu.Oto, co robię dla małych projektów z tylko marginalnym wykorzystaniem wywołań metod w tej samej klasie. Dokumentacja w kodzie jest zdecydowanie zalecana, ponieważ może wydawać się przerażająca dla kolegów. Ale jest łatwy do przetestowania, prosty, szybki do osiągnięcia i oszczędza mi pełnowartościowe oprzyrządowanie AspectJ. Jednak w przypadku bardziej intensywnego użytkowania radziłbym rozwiązanie AspectJ.
źródło
W moim przypadku dodaję zmienną:
Dlatego wywołuję tę
getEmployeeData
metodę przy użyciuaService
}
W tym przypadku użyje pamięci podręcznej.
źródło
Użyj statycznego tkania, aby utworzyć proxy wokół fasoli. W takim przypadku nawet metody „wewnętrzne” działałyby poprawnie
źródło
<iajc
kompilatora (od ant), który rozwiązuje wszystkie aspekty konieczności dla klas buforowalnych.W tym celu używam wewnętrznej wewnętrznej fasoli (
FactoryInternalCache
) z prawdziwą pamięcią podręczną:źródło
zdecydowanie najłatwiejszym rozwiązaniem jest odwołanie się w ten sposób:
źródło