Есть ли какая-либо причина, по которой вы хотите или должны кэшировать все Foos
в своем приложении вместе, а не по отдельности?
Имейте в виду, что по замыслу Spring's Cache Abstraction параметры метода (если есть) используются в качестве ключа, а возвращаемое значение — в качестве значения записи кэша. Если у метода нет параметров, то Spring сгенерирует для вас идентификатор.
Я написал о том, как настроить Spring CacheManager
для кэширования коллекции значений, возвращаемых методом @Cacheable
, по отдельности.
Однако на данный момент предположим, что вам нужно/хотите кэшировать весь список Foos
.
Затем, чтобы создать метод, который извлекает отдельный Foo
по идентификатору из кэшированного списка Foos
, вы могли бы, учитывая исходный кэшированный метод в классе обслуживания, сделать, например...
@Sevice
class MyFooService {
private final FooRepository<Foo, Long> fooRepository;
@Cacheable(cacheNames = "foos")
public List<FooDto> getAllFoos() {
return this.fooRepository.findAll().stream()
.map(FooEntityDomainToDtoMapper::mapDomainToDto) // mapping entity to dto
.collect(Collectors.toList());
}
}
Затем в другом компоненте приложения вы можете...
@Component
class MyFooAccessor {
private final MyFooService fooService;
MyFooAccessor(MyFooService fooService) {
this.fooService = fooService;
}
Optional<FooDto> getById(Long id) {
this.fooService.getAllFoos().stream()
.filter(fooDto -> fooDto.getId().equals(id))
.findFirst();
}
...
}
MyFooAccessor
следит за тем, чтобы вы не обходили прокси-сервер кэширования (т. е. AOP Proxy + Caching Advice вокруг MyFooService
, применяемый Spring). Если бы метод getById(..)
был членом класса MyFooService
и вызывал бы метод getAllFoos()
напрямую, вы бы обходили рекомендации по прокси и кэшированию, что каждый раз приводило бы к доступу к базе данных.
ПРИМЕЧАНИЕ. Вы можете использовать Spring AOP Load Time Weaving (LTW) (см. doc), чтобы избежать обхода кэширующего прокси-сервера, если вы хотите сохранить метод getById(:Long)
в классе MyFooService
с getAllFoos()
, @Cacheable
метод. Однако...
Как правило, вы можете решить проблемы такого рода путем (ре)структурирования вашего кода соответствующим образом, используя правильный шаблон проектирования. И это не единственное решение. Прелесть Spring заключается в том, что он дает вам много вариантов выбора. Это всего лишь 1 вариант.
Надеюсь, это поможет вам получить больше идей.
person
John Blum
schedule
28.09.2020