Я пытаюсь вызвать метод @Cacheable из того же класса.
И это не сработало. Из-за:
В режиме прокси (по умолчанию) перехватываются только вызовы внешних методов, поступающие через прокси. Это означает, что самовызов (фактически, метод в целевом объекте, который вызывает другой метод целевого объекта) не приводит к фактическому кэшированию во время выполнения, даже если вызванный метод отмечен @Cacheable. В этом случае рассмотрите возможность использования режима aspectj. Кроме того, прокси-сервер должен быть полностью инициализирован для обеспечения ожидаемого поведения, поэтому вы не должны полагаться на эту функцию в своем коде инициализации (то есть @PostConstruct).
Это означает, что @Cachable (также @Transactional) работает с прокси-классами, которые являются Spring AOP. Внутренний вызов в том же классе делает вызов с помощью 'this' вместо прокси-классов.
Чтобы решить проблему, я должен вызвать метод через прокси или с использованием AspectJ (другой АОП). Итак, я нашел 4 решения.
Какой ваш выбор? а почему другие не рекомендуются?
Пожалуйста, поделитесь своим мнением!
- с использованием AspectJ (другой АОП)
- получить Bean из ApplicationContext и использовать его
@Service
public class UserService implements Service {
@Autowired
private ApplicationContext applicationContext;
private Service self;
@PostConstruct
private void init() {
self = applicationContext.getBean(UserService.class);
}
}
самоавтоматизация с использованием @Resource // начиная с Spring 4.3
@Component
@CacheConfig(cacheNames = "SphereClientFactoryCache")
public class CacheableSphereClientFactoryImpl implements SphereClientFactory {
/**
* 1. Self-autowired reference to proxified bean of this class.
*/
@Resource
private SphereClientFactory self;
@Override
@Cacheable(sync = true)
public SphereClient createSphereClient(@Nonnull TenantConfig tenantConfig) {
// 2. call cached method using self-bean
return self.createSphereClient(tenantConfig.getSphereClientConfig());
}
@Override
@Cacheable(sync = true)
public SphereClient createSphereClient(@Nonnull SphereClientConfig clientConfig) {
return CtpClientConfigurationUtils.createSphereClient(clientConfig);
}
}
сделать Bean-область класса как «прототип» вместо «singleton»
@Service
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class AService {
private final AService _aService;
@Autowired
public AService(AService aService) {
_aService = aService;
}
@Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
..println("Cache is not being used");
...
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = _aService.getEmployeeData(date);
...
}
}
Я новичок ie весной :)
На самом деле , Я выбрал 4-е решение, но мне показалось, что это не лучший способ. потому что мне просто нужно вызвать метод кеширования через прокси, и для этого нужно сделать несколько bean-компонентов.
После прочтения статей я думаю, что AspectJ - лучший выбор. Это выглядит круто, Spring рекомендует это, и многие люди тоже рекомендуют.
Но я не понимаю, как работает AspectJ (буду изучать), и я также не знаю, почему другие не рекомендуются.
ссылок