Clean Architecture com Spring Boot: Guia Completo com Exemplo Prático

Introdução
A Clean Architecture com Spring Boot é uma abordagem de design que organiza o sistema em camadas bem definidas, promovendo baixo acoplamento, alta coesão e independência de frameworks.
Se você já enfrentou problemas como:
- código difícil de testar 😩
- regras de negócio espalhadas 🤯
- forte dependência do Spring 😬
… então este artigo vai te ajudar a resolver isso de forma estruturada.
O que é Clean Architecture?
A Clean Architecture foi proposta por Robert C. Martin (Uncle Bob) e tem como objetivo principal:
Separar regras de negócio da infraestrutura
Ou seja:
- O domínio não depende de banco
- O domínio não depende de framework
- O domínio é o coração da aplicação ❤️
Estrutura das Camadas

1. Domain (Entidades + Regras de Negócio)
- Entidades
- Value Objects
- Regras puras
public class Account {
private Long id;
private BigDecimal balance;
public void deposit(BigDecimal amount) {
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("Valor inválido");
}
this.balance = this.balance.add(amount);
}
}
👉 Não depende de Spring, JPA ou qualquer framework
2. Application (Use Cases)
- Casos de uso
- Orquestração do domínio
public class DepositUseCase {
private final AccountRepository repository;
public DepositUseCase(AccountRepository repository) {
this.repository = repository;
}
public void execute(Long accountId, BigDecimal amount) {
Account account = repository.findById(accountId);
account.deposit(amount);
repository.save(account);
}
}
3. Interface Adapters
- Controllers (REST)
- Mappers (DTO ↔ Domain)
- Presenters
@RestController
@RequestMapping("/accounts")
public class AccountController {
private final DepositUseCase depositUseCase;
public AccountController(DepositUseCase depositUseCase) {
this.depositUseCase = depositUseCase;
}
@PostMapping("/{id}/deposit")
public ResponseEntity deposit(@PathVariable Long id,
@RequestBody DepositRequest request) {
depositUseCase.execute(id, request.getAmount());
return ResponseEntity.ok().build();
}
}
4. Infrastructure
- Banco de dados
- Implementação de repositórios
- Configuração Spring
@Repository
public class AccountRepositoryImpl implements AccountRepository {
private final JpaAccountRepository jpaRepository;
public AccountRepositoryImpl(JpaAccountRepository jpaRepository) {
this.jpaRepository = jpaRepository;
}
@Override
public Account findById(Long id) {
return jpaRepository.findById(id)
.map(AccountMapper::toDomain)
.orElseThrow();
}
}
Regra de Dependência (A MAIS IMPORTANTE)
As dependências sempre apontam para dentro
Controller → UseCase → Domain
Repository → Domain
❌ Domain NÃO conhece:
- Spring
- Banco
- HTTP
📦 Estrutura de Pacotes Sugerida
com.seuprojeto
├── domain
│ ├── model
│ └── repository
│
├── application
│ └── usecase
│
├── infrastructure
│ ├── persistence
│ └── config
│
└── interfaces
├── controller
└── dto
Benefícios Reais
✅ Testabilidade
Você testa UseCase sem Spring:
@Test
void shouldDeposit() {
AccountRepository fakeRepo = new InMemoryAccountRepository();
DepositUseCase useCase = new DepositUseCase(fakeRepo);
useCase.execute(1L, BigDecimal.TEN);
assertEquals(BigDecimal.TEN, fakeRepo.findById(1L).getBalance());
}
Independência de Framework
Trocar:
- Spring → Micronaut
- JPA → JDBC
- REST → Kafka
👉 sem alterar o domínio
Organização para sistemas grandes
Perfeito para:
- microserviços complexos
- sistemas bancários 💰
- plataformas críticas
👉 (exatamente seu cenário hoje)
⚠️ Erros comuns
❌ Colocar @Entity no Domain
@Entity // ERRADO
public class Account { } assertEquals(BigDecimal.TEN, fakeRepo.findById(1L).getBalance());
}
👉 Isso acopla ao JPA
❌ Lógica no Controller
// ERRADO
if (amount > 0) {
account.setBalance(...)
}
👉 regra deve ficar no domínio
❌ Repository direto no Controller
👉 pula o UseCase → vira bagunça
Clean Architecture vs Hexagonal vs DDD
| Conceito | Foco |
| Clean Architecture | Separação de camadas |
| Hexagonal | Portas e adaptadores |
| DDD | Modelagem do domínio |
Quando usar?
Use Clean Architecture quando:
- Sistema vai crescer 📈
- Regras de negócio são complexas 🧠
- Precisa de alta manutenibilidade 🔧
Evite quando:
- CRUD simples
- MVP rápido
Conclusão
A Clean Architecture com Spring Boot não é apenas organização — é uma forma de garantir que seu sistema:
- sobreviva ao tempo ⏳
- seja fácil de testar 🧪
- evolua sem dor 😌
Se você quer evoluir como arquiteto, dominar esse conceito é essencial.
Share this content:
Vamos evoluir juntos em tecnologia, carreira e disciplina.
Acompanhe novos artigos sobre backend, arquitetura, performance e os aprendizados que também surgem no esporte. Um espaço para compartilhar conhecimento, consistência e evolução ao longo da jornada.