Новое:Talanto осенью: фильтры с числами, отклик по шагам и каталог компаний

+1 138новых вакансий за сутки·93 809вакансий открыто сейчас·Новое:Talanto осенью: фильтры с числами, отклик по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании7 271
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: фильтры с числами, отклик по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 409 кандидатов открыты к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python17 229
  • Облачные технологии14 182
  • QA вакансии3 456
  • Backend вакансии2 115
  • Инженер данных1 801
  • Продакт-менеджер1 247

Разработка

  • Android1 858
  • iOS1 698
  • Fullstack вакансии996
  • AI вакансии955
  • Frontend вакансии754
  • Mobile вакансии44

По стеку

  • Go8 752
  • Java6 596
  • Node.js2 036
  • .NET1 740
  • Kotlin1 618
  • Rust1 473
  • C#719
  • PHP690
  • C++580

DevOps и инфраструктура

  • Kubernetes7 788
  • DevOps вакансии6 103
  • Linux-инфраструктура5 508
  • Terraform / IaC4 290
  • CI/CD3 280
  • Мониторинг и Observability1 791
  • SRE566
  • Кибербезопасность454

Аналитика и данные

  • Data Scientist1 142
  • Бизнес-аналитик923
  • Аналитик данных859
  • Системный аналитик154

Другие направления

  • Проджект-менеджер623
  • UI/UX дизайн149
  • Ручное тестирование14

По регионам

  • Вакансии в США44 156
  • Вакансии в Европе24 035
  • Вакансии в Канаде4 532
  • Работа в России3 865

По формату

  • Удалённые вакансии74 994
  • Релокация в США44 154
  • Гибридная работа12 489
  • Офисная работа7 090

По уровню

  • Senior вакансии42 633
  • Middle вакансии20 958
  • Junior вакансии6 709

Сейчас нанимают

Все компании
  • Wise190 вакансий
  • Rakuten189 вакансий
  • ASML166 вакансий
  • Grab137 вакансий
  • Celonis38 вакансий
  • Spotify37 вакансий
  • Adyen29 вакансий
  • Infobip28 вакансий
  • Monzo20 вакансий
  • Darktrace17 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К подготовке по вакансии←К теме Spring BootВсе вопросы
Spring BootMiddleКодинг

Как реализовать кэширование в Spring Boot с помощью @Cacheable, @CacheEvict и @CachePut?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

Spring Cache Abstraction использует @Cacheable для чтения из кэша, @CachePut для принудительного обновления и @CacheEvict для инвалидации. Нужно добавить @EnableCaching и настроить CacheManager (Caffeine, Redis и т.д.).

Подключение и активация

<!-- Caffeine (in-memory) -->
<dependency>
  <groupId>com.github.ben-manes.caffeine</groupId>
  <artifactId>caffeine</artifactId>
</dependency>

<!-- Redis (distributed) -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
@SpringBootApplication
@EnableCaching   // обязательно — без этого аннотации игнорируются
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Кэширование в Spring Boot: @Cacheable, @CacheEvict, @CachePut

Spring Cache Abstraction предоставляет декларативный кэш через аннотации, независимо от конкретного провайдера. Провайдер подключается через CacheManager — в продакшне обычно Caffeine (in-memory) или Redis (распределённый).

Настройка CacheManager

# Caffeine через application.yml
spring:
  cache:
    type: caffeine
    caffeine:
      spec: maximumSize=1000,expireAfterWrite=10m

# Redis
spring:
  cache:
    type: redis
    redis:
      time-to-live: 600000   # 10 минут в мс
      cache-null-values: false

Для Caffeine с разными настройками под разные кэши используйте Java-конфигурацию:

@Configuration
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager manager = new CaffeineCacheManager();
        manager.setCacheNames(List.of("users", "products", "categories"));
        manager.registerCustomCache("users",
            Caffeine.newBuilder()
                .maximumSize(500)
                .expireAfterWrite(Duration.ofMinutes(5))
                .recordStats()   // для мониторинга через Micrometer
                .build());
        manager.registerCustomCache("products",
            Caffeine.newBuilder()
                .maximumSize(10_000)
                .expireAfterWrite(Duration.ofHours(1))
                .build());
        return manager;
    }
}

@Cacheable — чтение с кэшированием результата

@Service
public class ProductService {

    // Простое кэширование по одному ключу
    @Cacheable(cacheNames = "products", key = "#id")
    public Product findById(Long id) {
        return productRepository.findById(id)
            .orElseThrow(() -> new ProductNotFoundException(id));
    }

    // Составной ключ
    @Cacheable(cacheNames = "products", key = "#category + ':' + #page")
    public Page<Product> findByCategory(String category, int page, int size) {
        return productRepository.findByCategory(category, PageRequest.of(page, size));
    }

    // Условное кэширование — только для активных продуктов
    @Cacheable(
        cacheNames = "products",
        key = "#id",
        condition = "#id > 0",
        unless = "#result.status == T(com.example.ProductStatus).DRAFT"
    )
    public Product findActiveById(Long id) {
        return productRepository.findById(id).orElseThrow();
    }
}

@CachePut — принудительное обновление кэша

@CachePut всегда выполняет метод и записывает результат в кэш. Используется при обновлении данных, чтобы кэш не устарел:

@CachePut(cacheNames = "products", key = "#result.id")
public Product updateProduct(Long id, UpdateProductRequest req) {
    Product product = productRepository.findById(id).orElseThrow();
    product.setName(req.getName());
    product.setPrice(req.getPrice());
    return productRepository.save(product);
    // результат автоматически запишется в кэш
}

@CacheEvict — инвалидация кэша

// Удалить конкретную запись
@CacheEvict(cacheNames = "products", key = "#id")
public void deleteProduct(Long id) {
    productRepository.deleteById(id);
}

// Очистить весь кэш (например, при импорте данных)
@CacheEvict(cacheNames = "products", allEntries = true)
public void importProducts(List<Product> products) {
    productRepository.saveAll(products);
}

// Очистить ДО выполнения метода (beforeInvocation = true)
// Полезно когда метод может выбросить исключение
@CacheEvict(cacheNames = "users", key = "#userId", beforeInvocation = true)
public void deactivateUser(Long userId) {
    userRepository.deactivateById(userId);
}

// Комбинирование нескольких операций через @Caching
@Caching(
    evict = {
        @CacheEvict(cacheNames = "products", key = "#id"),
        @CacheEvict(cacheNames = "categories", allEntries = true)
    }
)
public void deleteProductAndInvalidateCategories(Long id) {
    productRepository.deleteById(id);
}

SpEL-выражения для ключей

// Доступ к полям аргумента
@Cacheable(cacheNames = "users", key = "#request.userId")
public User findUser(UserRequest request) { ... }

// Использование имени метода в ключе
@Cacheable(cacheNames = "reports", key = "#root.methodName + ':' + #year")
public Report generateReport(int year) { ... }

// Кастомный KeyGenerator
@Cacheable(cacheNames = "search", keyGenerator = "searchKeyGenerator")
public List<Product> search(SearchCriteria criteria) { ... }

Подводные камни

  • Self-invocation не работает — вызов this.findById(id) внутри того же бина обходит Spring AOP proxy; кэш не сработает. Инжектируйте бин сам в себя или выносите метод в отдельный бин.
  • @EnableCaching забыт — без этой аннотации на конфигурационном классе все кэш-аннотации молча игнорируются; метод выполняется каждый раз.
  • Сериализация в Redis — по умолчанию Spring Data Redis использует JdkSerializationRedisSerializer, который требует Serializable. При смене версии класса кэш содержит несовместимые данные. Используйте GenericJackson2JsonRedisSerializer.
  • condition vs unless — condition вычисляется ДО вызова метода (результат недоступен), unless — ПОСЛЕ (результат в #result). Использование #result в condition всегда даст null.
  • null в кэше — по умолчанию spring.cache.redis.cache-null-values=true. Если метод возвращает null (не найдено), null кэшируется и отдаётся при следующих запросах. Отключайте или обрабатывайте явно.
  • TTL по умолчанию бесконечен — без явного expireAfterWrite (Caffeine) или time-to-live (Redis) кэш никогда не инвалидируется. Это приводит к устаревшим данным после рестарта только одного из сервисов.
  • Cache stampede при высоком трафике — если кэш протухает, все одновременные запросы идут в БД. Используйте Caffeine refreshAfterWrite или распределённую блокировку для предотвращения stampede.
  • @Transactional + @CacheEvict порядок — при beforeInvocation = false (по умолчанию) инвалидация происходит после commit транзакции. Если транзакция откатится, кэш всё равно будет удалён — это корректно, но нужно понимать порядок.

Типичные ошибки

  • Путать термин «spring boot caching» с соседним механизмом Spring Boot.
  • Не называть границу lifecycle, transaction, thread или request для «spring boot caching».
  • Игнорировать production-эффекты «spring boot caching»: latency, SQL shape, memory, security или observability.

Что проверяет интервьюер

  • Попросить объяснить механизм «spring boot caching» на минимальном примере.
  • Проверить, видит ли кандидат failure mode и диагностику для «spring boot caching».
  • Уточнить, какие настройки или API меняют «spring boot caching» в реальном сервисе.

Как вы знаете этот вопрос?

Проверить себя по теме Spring Boot →

Источники

  • https://docs.spring.io/spring-boot/reference/io/caching.html
←Предыдущий вопросКакие production-риски есть у Spring Boot: blocking code, connection pooling, config, auth, observability, deploy или graceful shutdown?Следующий вопрос→Проект на Spring Boot вырос из MVP в большой production-сервис. Какие проблемы архитектуры и сопровождения вы ожидаете увидеть?

Связанные темы

Spring Bootarchitecture-tradeoffsimplementationproduction-readiness

Вакансии с этим навыком

  • Fullstack Developer (Java Core & React)
  • Senior Java Engineer (Azure, PostgreSQL)
  • Senior Java Developer
  • Fullstack Software Engineer (with Java)
  • Senior Java Developer

Частые вопросы на собеседовании

  • Как реализовать health checks в Spring Boot Actuator?
  • Что делает аннотация @SpringBootApplication?
  • Что такое Spring Boot и чем он отличается от Spring Framework?
  • В каких backend-проектах Spring Boot является сильным выбором, а где лучше выбрать более простой или другой стек?