Gymterview
middle

Что такое Spring Event? Как создать и обработать событие?

Spring Events – механизм публикации и обработки событий, реализующий паттерн Observer (Наблюдатель). Позволяет ослабить связность между компонентами.

Создание события (Spring 4.2+ – просто POJO)

Пример
public class OrderCreatedEvent {
    private final Long orderId;
    private final Long userId;
    private final BigDecimal amount;
    // конструктор, геттеры
}

Публикация события

Пример
@Service
public class OrderService {
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    @Transactional
    public Order createOrder(CreateOrderRequest request) {
        Order order = orderRepository.save(new Order(request));
        eventPublisher.publishEvent(new OrderCreatedEvent(
                order.getId(), order.getUserId(), order.getAmount()));
        return order;
    }
}

Обработка события

Пример
@Component
public class OrderEventListener {

    // Синхронный (в той же транзакции!)
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        log.info("Заказ {} создан", event.getOrderId());
    }

    // Асинхронный (в отдельном потоке)
    @Async
    @EventListener
    public void sendNotification(OrderCreatedEvent event) {
        emailService.sendOrderConfirmation(event.getUserId());
    }

    // После коммита транзакции
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void afterOrderCommitted(OrderCreatedEvent event) {
        // выполнится только если транзакция успешно закоммичена
    }

    // Условная обработка
    @EventListener(condition = "#event.amount > 10000")
    public void handleLargeOrder(OrderCreatedEvent event) {
        auditService.flagForReview(event.getOrderId());
    }
}

На собеседовании: ключевое – @TransactionalEventListener для гарантии, что обработчик выполнится только после коммита. Частая ошибка – использовать синхронный @EventListener для долгих операций (отправка email) внутри транзакции. Используйте @Async или @TransactionalEventListener(phase = AFTER_COMMIT).