Spring cache @Cacheable метод игнорируется при вызове из одного класса
Я пытаюсь вызвать метод @Cacheable
из одного класса:
@Cacheable(value = "defaultCache", key = "#id")
public Person findPerson(int id) {
return getSession().getPerson(id);
}
public List<Person> findPersons(int[] ids) {
List<Person> list = new ArrayList<Person>();
for (int id : ids) {
list.add(findPerson(id));
}
return list;
}
и надеемся, что результаты из findPersons
также кэшируются, но аннотация @Cacheable
игнорируется, а метод findPerson
выполняется каждый раз.
Я делаю что-то неправильно здесь, или это предназначено?
Ответы
Ответ 1
Это связано с тем, как создаются прокси-серверы для обработки кэширования, связанные с транзакциями функции в Spring. Это очень хорошая ссылка на то, как Spring обрабатывает его - Транзакции, кеширование и АОП: понимание использования прокси в Spring
Короче говоря, самозапуск обходит динамический прокси-сервер, и любая перекрестная проблема, такая как кеширование, транзакция и т.д., которая является частью динамической логики прокси, также обойдена.
Исправление заключается в использовании времени компиляции AspectJ или времени загрузки.
Ответ 2
Вот что я делаю для небольших проектов с ограниченным использованием вызовов методов внутри одного класса. Внутрикодовая документация настоятельно рекомендуется, так как это может показаться неудачным для коллег. Но его легко проверить, просто, быстро достичь и избавит меня от полномасштабного инструментария AspectJ. Однако для более интенсивного использования я бы посоветовал решение AspectJ.
@Service
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class PersonDao {
private final PersonDao _personDao;
@Autowired
public PersonDao(PersonDao personDao) {
_personDao = personDao;
}
@Cacheable(value = "defaultCache", key = "#id")
public Person findPerson(int id) {
return getSession().getPerson(id);
}
public List<Person> findPersons(int[] ids) {
List<Person> list = new ArrayList<Person>();
for (int id : ids) {
list.add(_personDao.findPerson(id));
}
return list;
}
}
Ответ 3
Для тех, кто использует плагин Grails Spring Cache, обходной путь описан в документации. У меня была эта проблема в приложении grails, но, к сожалению, принятый ответ кажется непригодным для Grails. Решение является уродливым, IMHO, но оно работает.
Пример кода демонстрирует это хорошо:
class ExampleService {
def grailsApplication
def nonCachedMethod() {
grailsApplication.mainContext.exampleService.cachedMethod()
}
@Cacheable('cachedMethodCache')
def cachedMethod() {
// do some expensive stuff
}
}
Просто замените exampleService.cachedMethod() своим собственным сервисом и методом.
Ответ 4
Внутренняя конфигурация кэша может использоваться для "проксификации" вызовов метода, см. пример в этом ответе: stackoverflow.com/a/48168762/907576
Ответ 5
Можете ли вы помочь мне определить Java-бин PersonDAO в конфигурации Java?