Я не могу заставить кеш Spring работать правильно с методами, переопределенными в подклассе, также реализованном в суперклассе. Например, у меня есть этот абстрактный сервис:
public interface CrudService<E, I> {
void deleteById(I id);
E create(E item);
}
public abstract class CrudServiceImpl<E, I> {
void deleteById(I id) { // do things }
...
}
У меня есть несколько сервисов, расширяющих этот абстрактный класс для разных сущностей (E) и типов идентификаторов (I). Я хочу кэшировать только один из них:
public interface LocationService extends CrudService<Location, String> {
@CacheEvict("location")
@Override
void deleteById(String id);
@Cacheable("location")
List<Location> find();
}
@Service
public class LocationServiceImpl extends CrudServiceImpl<Location, String> implements LocationService {
public List<Location> find() { // do things }
}
Метод найти определен только в LocationService, а не в абстрактном классе. Когда я вызываю эти методы из компонента, который также имеет абстрактный класс:
public abstract class CrudManager<E, I> {
@Autowired
private CrudService<E, I> crudService;
public void doDelete(I id) {
crudService.deleteById(id);
}
}
@Component
public class LocationManager extends CrudManager<Location, String> {
@Autowired
private LocationService locationService;
public List<Location> doFind() {
return locationService.find();
}
}
Я подтвердил, что когда вызывается LocationManager.doFind, он запускает операции кэширования, определенные в LocationService, а LocationManager.doDelete — нет.
Я отлаживал до тех пор, пока AbstractFallbackCacheOperationSource.getCacheOperations не понял, что метод поиска операций:
public default void com.ontech.plantcore.service.LocationService.deleteById(java.lang.Object)
с targetClass = LocationServiceImpl.class вместо моего аннотированного метода LocationService.deleteById(java.lang.String). Таким образом, ClassUtils.getMostSpecificMethod не может найти аннотированный метод, и никакие операции не возвращаются. Это происходит с Spring 4.3.14 и 4.1.9.
Если я добавлю конкретный вызов в LocationManager к locationService.deleteById, он сработает, но это просто разрушит наследование.
Я вижу, что это связано со стиранием текста, но я не знаю, как заставить его работать правильно?
Я не включил его для упрощения. Извините, я только что изменил пример метода и дополнил некоторые недостающие параметры.
Поделиться ссылкой на репозиторий github было бы гораздо удобнее, чем анализировать код в тексте. Какая это версия Spring Framework?
Spring 4.3.14 и 4.1.9 тоже. Ну, пример довольно простой.




В Документация по кэшу Spring говорится, что аннотация @Cache* к методу интерфейса не работает с прокси-серверами на основе классов. Таким образом, вы должны добавить @Cache* к каждому методу класса, который хотите кэшировать.
Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Cache* annotation, as opposed to annotating interfaces. You certainly can place the @Cache* annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies (proxy-target-class = "true") or the weaving-based aspect (mode = "aspectj"), then the caching settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a caching proxy, which would be decidedly bad.
Я никогда не говорил, что использую прокси на основе классов. Я действительно не использую их, что является конфигурацией по умолчанию, поэтому правильно аннотировать интерфейсы. Во всяком случае, я уже пробовал размещать аннотации в классах и ничего не меняет. Я проверил, что объект обернут прокси. Но проблема в коде Spring, который определяет, есть ли у метода аннотации кеша, что из-за стирания типа метод пропускается.
Где код про
LocationManager.create?