Aula 18 - Processamento Assíncrono com Spring Events 📬
Objetivo Pedagógico
Objetivo: Implementação do padrão Event-Driven Architecture em aplicações Spring Boot através de ApplicationEventPublisher, @EventListener e processamento assíncrono com @Async.
📑 1. Fundamentos Teóricos & Análise Técnica
Em aplicações empresariais robustas, o princípio do Desacoplamento de Domínio dita que um serviço principal (como o fechamento de um pedido comercial) não deve ter conhecimento nem dependência direta de ações secundárias (como disparo de notificações por e-mail, atualização de pontos de fidelidade ou auditoria fiscal).
O ecossistema Spring fornece um subsistema nativo para orquestrar essa comunicação através do padrão Observer / Publisher-Subscriber: 1. Publicador (ApplicationEventPublisher): O serviço de negócio injeta o publicador e emite um evento de domínio (publisher.publishEvent(new OrderCreatedEvent(order))). 2. Ouvinte (@EventListener): Classes especializadas assinam o evento e reagem à sua ocorrência de forma isolada. 3. Execução Não-Bloqueante (@Async): Com a anotação @Async, o método do ouvinte é executado em uma thread separada gerenciada por um pool de execução (ThreadPoolTaskExecutor), liberando a thread da requisição HTTP imediatamente sem reter o usuário.
📐 Arquitetura Conceitual & Diagrama de Fluxo
sequenceDiagram
autonumber
actor Client as Cliente HTTP
participant Service as OrderService (Thread Principal)
participant Publisher as ApplicationEventPublisher
participant Listener as EmailNotificationListener (Thread Pool Async)
Client->>Service: POST /orders (Criar Pedido)
Service->>Service: Salva Pedido no Banco de Dados
Service->>Publisher: publishEvent(OrderCreatedEvent)
Service-->>Client: 201 Created (Resposta Imediata!)
Publisher->>Listener: Dispara Evento em Background (@Async)
Note over Listener: Envio de E-mail Executado sem Atrasar a API! 🔍 Pilares e Diretrizes Técnicas
Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Desacoplamento de Domínio: O serviço de pedidos não importa nem depende de classes de infraestrutura de e-mail. - Pool de Threads Parametrizado: Configuração de corePoolSize, maxPoolSize e queueCapacity no TaskExecutor. - Eventos Transacionais (@TransactionalEventListener): Garantia de que o evento seja disparado apenas após a confirmação do commit no banco. - Resiliência a Falhas de E-mail: Se o envio de e-mail falhar, a transação da compra não é revertida indevidamente.
🛠️ 2. Implementação Prática em Java, Spring Boot e Event-Driven Architecture
Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:
// OrderCreatedListener.java (Ouvinte Assíncrono de Eventos de Domínio)
package com.empresa.core.events;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
public record OrderCreatedEvent(String orderId, String customerEmail, double amount) {}
@Component
public class OrderEventsListener {
@Async("asyncTaskExecutor")
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleOrderCreated(OrderCreatedEvent event) {
System.out.println("[Thread Async: " + Thread.currentThread().getName() +
"] Enviando e-mail de confirmação para: " + event.customerEmail());
// Simula comunicação com provedor externo de e-mail
try {
Thread.sleep(3000);
} catch (InterruptedException ignored) {}
System.out.println("[Thread Async] E-mail enviado com sucesso para pedido: " + event.orderId());
}
}
💡 Análise Passo a Passo do Código
- Fase AFTER_COMMIT:
@TransactionalEventListenergarante que o e-mail só seja enviado se o pedido for salvo com sucesso na base de dados. - Execução @Async: O método é descarregado para o pool de threads
asyncTaskExecutor, não travando a resposta HTTP. - Java Record Imutável: Uso de
recordpara criar objetos de eventos leves, imutáveis e livres de código boilerplate.
🎯 3. Próximos Passos & Sequência Didática
-
Slides da Aula
-
Quiz de Fixação
-
Exercícios Práticos
-
Desafio de Projeto