Абстракция кеша Spring (AdviceMode.ASPECTJ) не работает внутри репозиториев spring-data-jpa
Я использую spring-data-jpa 1.9.0.RELEASE и хочу использовать механизм пружинного кэширования внутри моих репозиториев, например
public interface LandDao extends CrudRepository<Land, Long> {
@Cacheable("laender")
Land findByName(String land)
}
Вот моя конфигурация кеша:
@Configuration
@EnableCaching(mode=AdviceMode.ASPECTJ)
public class EhCacheConfiguration extends CachingConfigurerSupport {
...
Обратите внимание, что я использую AdviceMode.ASPECTJ (время компиляции). К сожалению, кэширование не работает при вызове метода репо findByName. Изменение режима кэширования на AdviceMode.PROXY все работает нормально.
Чтобы гарантировать, что кэширование в принципе работает с aspectJ, я написал следующую службу:
@Service
public class LandService {
@Autowired
LandDao landDao;
@Cacheable("landCache")
public Land getLand(String bez) {
return landDao.findByName(bez);
}
}
В этом случае кеш работает как брелок. Поэтому я думаю, что все части моего приложения настроены правильно, и проблема заключается в сочетании режима кэширования spring-data-jpa и AspectJ. У кого-нибудь есть идея, что здесь происходит не так?
1 ответ
Хорошо, нашел ответ на мой вопрос самостоятельно. Javadoc ответственного аспекта org.springframework.cache.aspectj.AnnotationCacheAspect гласит:
При использовании этого аспекта необходимо аннотировать класс реализации (и / или методы в этом классе), а не интерфейс (если есть), который реализует этот класс. AspectJ следует правилу Java, согласно которому аннотации на интерфейсах не наследуются.
Поэтому невозможно использовать аннотацию @Cacheable внутри интерфейсов репозитория вместе с aspectj. Мое решение сейчас заключается в использовании пользовательских реализаций для репозиториев Spring Data:
Интерфейс для пользовательских функций хранилища:
public interface LandRepositoryCustom {
Land findByNameCached(String land);
}
Реализация пользовательских функций хранилища с использованием запроса dsl:
@Repository
public class LandRepositoryImpl extends QueryDslRepositorySupport
implements LandRepositoryCustom {
@Override
@Cacheable("landCache")
public Land findByNameCached(String land) {
return from(QLand.land).where(QLand.land.name.eq(land)).singleResult(QLand.land);
}
}
Обратите внимание на аннотацию @Cacheable для метода findByNameCached.
Базовый интерфейс репозитория:
public interface LandRepository extends CrudRepository<Land, Long>, LandRepositoryCustom {
}
Используя репозиторий:
public class SomeService {
@Autowired
LandRepository landDao;
public void foo() {
// Cache is working here:-)
Land land = landDao.findByNameCached("Germany");
}
}
Было бы полезно добавить примечание, касающееся этого ограничения, в ссылку на данные пружины.