Расскажите о случае, когда вы проектировали или улучшали сервис на Spring Framework с учётом транзакций, безопасности, фоновых задач или мониторинга.
Проектировал платёжный сервис на Spring Framework 5: @Transactional с REQUIRES_NEW для аудит-лога, HMAC-валидация вебхуков через OncePerRequestFilter, Transactional Outbox для надёжной отправки уведомлений, кастомные метрики через Micrometer.
Контекст задачи
На одном из проектов я проектировал платёжный микросервис на Spring Framework 5.3 (без Spring Boot). Задача: принимать вебхуки от платёжного шлюза, записывать события в БД, отправлять уведомления, собирать метрики — надёжно, с retry и без потери данных.
Транзакции
Использовал @Transactional на сервисном слое с propagation = REQUIRED и явным rollbackFor = PaymentException.class. Для аудит-лога (не должен откатываться вместе с основной транзакцией) вынес в отдельный сервис с REQUIRES_NEW. Настроил PlatformTransactionManager вручную через @Configuration:
@Bean
public PlatformTransactionManager transactionManager(DataSource ds) {
return new DataSourceTransactionManager(ds);
}
Безопасность
Подключил Spring Security 5 с кастомным WebSecurityConfigurerAdapter: HMAC-валидация подписи вебхука в OncePerRequestFilter, IP-allowlist через HasIpAddress. Все эндпоинты, кроме /webhook, требовали JWT.
Фоновые задачи
Уведомления отправлял через @Scheduled(fixedDelay = 5000) с выборкой из outbox-таблицы (паттерн Transactional Outbox). Задача атомарно обновляла статус записи и отправляла email — без риска потери события при перезапуске.
Мониторинг
Зарегистрировал кастомные метрики через Micrometer MeterRegistry: счётчик успешных и неудачных платежей, histogram времени обработки вебхука. Подключил PrometheusRegistry и настроил Grafana-алерт на payment_failures_total > 10 за 5 минут.
Подводные камни
- Self-invocation: при вызове
@Transactional-метода черезthisтранзакция не открывалась — потребовалась инъекция себя черезApplicationContext. @ScheduledбезShedLockзапускался на всех подах при горизонтальном масштабировании — двойная отправка уведомлений.- При ручной конфигурации без Spring Boot важно явно включить
@EnableTransactionManagementи@EnableScheduling. - Spring Security 5
WebSecurityConfigurerAdapterdeprecated в 6.x — при миграции потребовалась переработка конфигурации. - Без
@EnableAspectJAutoProxy(proxyTargetClass = true)AOP-прокси не оборачивали классы без интерфейсов. - Transactional Outbox требует индекс на поле статуса — без него full scan таблицы на каждом тике scheduler-а.
What hurts your answer
- Выдумывать опыт или говорить слишком общими фразами
- Не объяснять свою личную роль в работе с Spring Framework
- Не показывать результат, метрики или извлечённые уроки
What they're listening for
- Может подготовить честный пример использования Spring Framework
- Показывает свою роль, решения и результат
- Умеет рефлексировать над trade-offs и уроками