Gymterview
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).