middle
Что такое Spring Cache и как его использовать?
Spring Cache – абстракция кэширования, позволяющая декларативно (через аннотации) кэшировать результаты методов без привязки к конкретной реализации кэша.
Подключение
Пример
@SpringBootApplication
@EnableCaching
public class MyApplication { }
Основные аннотации
Пример
@Service
public class UserService {
// Кэширует результат. При повторном вызове с тем же ключом
// метод НЕ выполняется, результат берётся из кэша
@Cacheable(value = "users", key = "#id")
public UserDto findById(Long id) {
return userRepository.findById(id).map(this::toDto).orElseThrow();
}
// Условное кэширование
@Cacheable(value = "users", key = "#id", unless = "#result == null")
public UserDto findByIdConditional(Long id) { }
// Всегда выполняет метод и обновляет кэш
@CachePut(value = "users", key = "#result.id")
public UserDto updateUser(UpdateUserRequest request) { }
// Удаляет запись из кэша
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) { }
// Очистка всего кэша
@CacheEvict(value = "users", allEntries = true)
public void clearUsersCache() { }
}
Реализации кэша
По умолчанию Spring использует ConcurrentMapCacheManager (простой HashMap). Для production:
Пример
# Redis
spring.cache.type=redis
spring.cache.redis.time-to-live=600000
# Caffeine (in-memory, рекомендуется для одного экземпляра)
spring.cache.type=caffeine
spring.cache.caffeine.spec=maximumSize=500,expireAfterWrite=10m
На собеседовании: ключевое – знание аннотаций (
@Cacheable,@CachePut,@CacheEvict) и их различий. Частая ошибка – забыть инвалидировать кэш при обновлении данных. Также проблема self-invocation: вызов@Cacheable-метода из того же класса не кэшируется (та же проблема, что и с@Transactional).