Pular para o conteúdo principal

Módulo 18: Perguntas de Entrevista Spring Boot

Objetivos​

Este módulo prepara você para entrevistas técnicas em desenvolvimento Java/Spring Boot. As perguntas estão organizadas por nível de dificuldade e por tema, cobrindo os tópicos mais frequentemente abordados em entrevistas.

Conselho

Não decore as respostas palavra por palavra. Entenda os conceitos e seja capaz de explicá-los com suas próprias palavras e exemplos concretos.


Capítulos do Módulo​

#CapítuloConteúdo
1JPA & Banco de DadosProblema N+1, Lazy/Eager loading, @Transactional, paginação, relações entre entidades
2Exercícios de RefatoraçãoGuard clauses, Strategy Pattern, SRP (God Class), constantes mágicas, composição vs herança
3Algoritmos & Estruturas de DadosHashMap, Stack, LinkedList, Binary Search, Two Sum, FizzBuzz, anagramas
4Design REST & Design PatternsAPI REST, Builder, Singleton, Observer com Spring Events
5Depuração & Code ReviewEncontrar bugs, code review, vazamento de memória, concorrência, exceções, code smells
6Armadilhas Fundamentais do Java== vs .equals(), hashCode(), final, static, String imutável, Optional, passagem por valor
7Coleções JavaList.of() vs new ArrayList<>(), HashMap, HashSet, Stream API, thread-safety, iteração
8"O que é...?" — 30 conceitosDTO, MVC, API REST, CRUD, POJO, Bean, IoC, ORM/JPA, Maven, Docker, JWT, CORS, Lombok, Record...

Nível 1 : Perguntas Fundamentais​

Q1. O que é Spring Boot e em que ele difere do Spring Framework?​

Resposta esperada:

Spring Boot é um framework construído sobre o Spring Framework que simplifica a configuração e o deploy. As principais diferenças:

AspectoSpring FrameworkSpring Boot
ConfiguraçãoManual (XML ou Java)Auto-configuração
ServidorServidor externo necessárioServidor embutido (Tomcat)
DependênciasGerenciadas individualmenteStarters pré-configurados
InicializaçãoComplexamain() + @SpringBootApplication

Spring Boot não substitui o Spring, ele o torna mais fácil de usar.


Q2. O que faz a anotação @SpringBootApplication?​

Resposta esperada:

É uma meta-anotação que combina três anotações:

  • @SpringBootConfiguration : indica uma classe de configuração Spring
  • @EnableAutoConfiguration : ativa a auto-configuração baseada nas dependências do classpath
  • @ComponentScan : escaneia o pacote atual e seus subpacotes para encontrar os beans

Q3. O que é injeção de dependências (DI)?​

Resposta esperada:

Injeção de dependências é um padrão de design onde as dependências de um objeto são fornecidas de fora, ao invés de serem criadas pelo próprio objeto.

// SEM DI (alto acoplamento)
public class OrderService {
private UserRepository repo = new UserRepository(); // Cria sua própria dependência
}

// COM DI (baixo acoplamento)
public class OrderService {
private final UserRepository repo;

public OrderService(UserRepository repo) { // Injetada externamente
this.repo = repo;
}
}

Vantagens: testabilidade, baixo acoplamento, flexibilidade.


Q4. Qual a diferença entre @Controller e @RestController?​

Resposta esperada:

  • @Controller retorna nomes de views (templates HTML). Para retornar JSON, é necessário adicionar @ResponseBody em cada método.
  • @RestController = @Controller + @ResponseBody. Cada método retorna diretamente dados serializados em JSON.

Q5. Quais são os diferentes escopos de bean no Spring?​

Resposta esperada:

EscopoDescrição
singletonUma única instância por container (padrão)
prototypeNova instância a cada injeção
requestUma instância por requisição HTTP
sessionUma instância por sessão HTTP
applicationUma instância por ServletContext

Q6. Qual a diferença entre application.properties e application.yml?​

Resposta esperada:

Mesma funcionalidade, sintaxe diferente:

# application.properties (chave=valor, plano)
server.port=8080
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
# application.yml (hierárquico, mais legível)
server:
port: 8080
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb

YAML é mais legível para configurações aninhadas, mas cuidado com a indentação.


Q7. O que é um Starter do Spring Boot?​

Resposta esperada:

Um starter é um conjunto de dependências pré-configuradas para um uso específico:

  • spring-boot-starter-web : aplicação web (Tomcat, Spring MVC, Jackson)
  • spring-boot-starter-data-jpa : persistência (Hibernate, Spring Data JPA)
  • spring-boot-starter-security : segurança (Spring Security)
  • spring-boot-starter-test : testes (JUnit, Mockito, MockMvc)

Eles evitam o gerenciamento manual de compatibilidade entre versões.


Nível 2 : Perguntas Intermediárias​

Q8. Explique a arquitetura em camadas de uma aplicação Spring Boot.​

Resposta esperada:

Cliente HTTP
↓
┌─────────────────┐
│ Controller │ Recebe as requisições, valida, retorna as respostas
├─────────────────┤
│ Service │ Lógica de negócio, regras de negócio, orquestração
├─────────────────┤
│ Repository │ Acesso a dados (CRUD, queries no banco)
├─────────────────┤
│ Database │ PostgreSQL, MySQL, H2...
└─────────────────┘

Cada camada só se comunica com a camada imediatamente abaixo. O Controller nunca acessa diretamente o Repository.


Q9. Qual a diferença entre JpaRepository, CrudRepository e PagingAndSortingRepository?​

Resposta esperada:

JpaRepository (mais completo)
↑ herda de
PagingAndSortingRepository (paginação + ordenação)
↑ herda de
CrudRepository (CRUD básico)
↑ herda de
Repository (marcador)
  • CrudRepository : save(), findById(), findAll(), deleteById()
  • PagingAndSortingRepository : adiciona findAll(Pageable), findAll(Sort)
  • JpaRepository : adiciona flush(), saveAndFlush(), deleteInBatch(), retorna List ao invés de Iterable

Na prática, quase sempre usamos JpaRepository.


Q10. Como funciona a auto-configuração no Spring Boot?​

Resposta esperada:

O Spring Boot examina o classpath na inicialização e configura automaticamente os beans necessários:

  1. Se spring-boot-starter-data-jpa está no classpath E existe uma DataSource configurada → auto-configura Hibernate, EntityManager, etc.
  2. Se spring-boot-starter-web está no classpath → auto-configura Tomcat, Jackson, DispatcherServlet
  3. As anotações @ConditionalOn... determinam se uma auto-configuração se aplica

Sempre é possível sobrescrever os beans auto-configurados com nossos próprios @Bean.


Q11. O que são Spring Profiles e para que servem?​

Resposta esperada:

Os profiles permitem carregar configurações diferentes conforme o ambiente:

# application-dev.yml
spring:
datasource:
url: jdbc:h2:mem:devdb

# application-prod.yml
spring:
datasource:
url: jdbc:postgresql://prod-server:5432/mydb

Ativação: --spring.profiles.active=prod ou SPRING_PROFILES_ACTIVE=prod

Também é possível condicionar beans com @Profile("dev").


Q12. Explique a diferença entre @Transactional de leitura e de escrita.​

Resposta esperada:

@Transactional(readOnly = true)   // Leitura: otimização do Hibernate (sem dirty checking)
public List<User> findAll() { ... }

@Transactional // Escrita: commit se sucesso, rollback se exceção
public User create(UserDto dto) { ... }

Boa prática: Colocar @Transactional(readOnly = true) no nível da classe de serviço, e @Transactional apenas nos métodos de escrita.


Q13. Como tratar exceções em uma API REST Spring Boot?​

Resposta esperada:

Três abordagens, da mais local à mais global:

  1. @ExceptionHandler em um controller (escopo local)
  2. @RestControllerAdvice com @ExceptionHandler (escopo global)
  3. @ResponseStatus em uma exceção customizada

A melhor prática é o @RestControllerAdvice global que centraliza todo o tratamento de erros.


Q14. O que é o problema N+1 no JPA e como resolvê-lo?​

Resposta esperada:

O problema N+1 ocorre quando uma entidade é carregada e o JPA executa N queries adicionais para carregar as relações:

1 query para carregar 100 departamentos
+ 100 queries para carregar os funcionários de cada departamento
= 101 queries ao invés de 1 ou 2

Soluções:

  • JOIN FETCH em JPQL : @Query("SELECT d FROM Department d JOIN FETCH d.employees")
  • @EntityGraph : @EntityGraph(attributePaths = {"employees"})
  • @BatchSize : carrega as relações em lotes

Q15. Como proteger uma API REST com JWT?​

Resposta esperada:

O fluxo JWT:

1. Cliente envia login/senha → POST /api/auth/login
2. Servidor verifica as credenciais
3. Se OK → gera um JWT assinado e retorna
4. Cliente armazena o JWT
5. Para cada requisição → Authorization: Bearer <token>
6. JwtAuthenticationFilter extrai e valida o token
7. Se válido → autentica o usuário no SecurityContext

Componentes chave: JwtService (geração/validação), JwtAuthenticationFilter (filtro), SecurityConfig (configuração).


Nível 3 : Perguntas Avançadas​

Q16. Explique o padrão IoC (Inversion of Control) no Spring.​

Resposta esperada:

IoC inverte o fluxo de controle: ao invés do código criar suas dependências, o container Spring as cria e injeta.

O container Spring (ApplicationContext) é responsável por:

  1. Criar os objetos (beans)
  2. Configurar os objetos
  3. Montar as dependências
  4. Gerenciar o ciclo de vida

A injeção de dependências (DI) é o principal mecanismo de IoC no Spring.


Q17. Qual a diferença entre @Component, @Service, @Repository e @Controller?​

Resposta esperada:

Tecnicamente, os quatro são @Component. A diferença é semântica (papel na arquitetura):

  • @Component : bean genérico
  • @Service : lógica de negócio
  • @Repository : acesso a dados + tradução automática de exceções SQL para exceções Spring
  • @Controller : manipulação de requisições web

Usar a anotação correta ajuda na legibilidade e permite tratamentos específicos (ex: tradução de exceções para @Repository).


Q18. Como implementar paginação no Spring Data JPA?​

Resposta esperada:

// Repository
public interface UserRepository extends JpaRepository<User, Long> {
Page<User> findByRole(Role role, Pageable pageable);
}

// Controller
@GetMapping("/users")
public Page<User> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(defaultValue = "name") String sortBy) {
Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
return userRepository.findAll(pageable);
}

O Page<T> retornado contém: conteúdo, número da página, tamanho, total de elementos, número de páginas.


Q19. Explique as diferentes estratégias de propagação do @Transactional.​

Resposta esperada:

PropagaçãoComportamento
REQUIRED (padrão)Junta-se à transação existente ou cria uma nova
REQUIRES_NEWSempre cria uma nova transação (suspende a existente)
SUPPORTSJunta-se se existir, senão executa sem transação
NOT_SUPPORTEDSempre executa sem transação (suspende a existente)
MANDATORYExige transação existente, senão lança exceção
NEVERNão pode haver transação, senão lança exceção
NESTEDTransação aninhada (savepoint)

Caso de uso frequente do REQUIRES_NEW: log de auditoria que deve persistir mesmo se a transação principal falhar.


Q20. Como otimizar a performance de uma aplicação Spring Boot?​

Resposta esperada:

  1. JPA/Hibernate:

    • Evitar o problema N+1 (JOIN FETCH, EntityGraph)
    • Usar @Transactional(readOnly = true) para leituras
    • Projeções DTO ao invés de entidades completas
    • Paginação sistemática
  2. Cache:

    • @Cacheable com Spring Cache (Redis, Caffeine)
    • Cache HTTP (ETag, Cache-Control)
  3. Configuração:

    • Connection pooling (HikariCP bem configurado)
    • Compressão GZIP
    • Perfis otimizados para produção
  4. Arquitetura:

    • Operações assíncronas (@Async)
    • Indexação adequada no banco de dados
    • Lazy loading das relações

Q21. O que é Spring Actuator e quais endpoints úteis ele fornece?​

Resposta esperada:

Spring Actuator fornece endpoints de monitoramento e gerenciamento:

EndpointDescrição
/actuator/healthEstado da aplicação (UP/DOWN)
/actuator/infoInformações da aplicação
/actuator/metricsMétricas (memória, CPU, requisições)
/actuator/envVariáveis de ambiente
/actuator/beansLista de todos os beans
/actuator/mappingsTodos os endpoints REST
/actuator/loggersConfiguração dos loggers
/actuator/prometheusMétricas no formato Prometheus

Em produção, é necessário proteger esses endpoints e expor apenas /health e /info publicamente.


Q22. Explique o ciclo de vida de um bean Spring.​

Resposta esperada:

1. Instanciação (construtor)
2. Injeção de dependências (@Autowired)
3. Aware interfaces (BeanNameAware, ApplicationContextAware...)
4. BeanPostProcessor.postProcessBeforeInitialization()
5. @PostConstruct
6. InitializingBean.afterPropertiesSet()
7. init-method customizado
8. BeanPostProcessor.postProcessAfterInitialization()
9. ══════ Bean pronto para uso ══════
10. @PreDestroy
11. DisposableBean.destroy()
12. destroy-method customizado

Na prática, usamos principalmente @PostConstruct e @PreDestroy.


Q23. Como implementar um padrão CQRS simplificado com Spring Boot?​

Resposta esperada:

CQRS (Command Query Responsibility Segregation) separa operações de leitura e escrita:

// Command (escrita)
@Service
@Transactional
public class UserCommandService {
public User create(CreateUserCommand cmd) { ... }
public void update(UpdateUserCommand cmd) { ... }
public void delete(Long id) { ... }
}

// Query (leitura)
@Service
@Transactional(readOnly = true)
public class UserQueryService {
public UserDto findById(Long id) { ... }
public Page<UserDto> findAll(Pageable page) { ... }
}

Isso permite otimizar leituras e escritas separadamente (ex: projeções DTO para leitura, validações complexas para escrita).


Perguntas Comportamentais / Cenários​

Q24. Você precisa projetar uma API REST para um sistema de e-commerce. Quais endpoints você criaria?​

Resposta esperada:

Products:
GET /api/products → Lista paginada
GET /api/products/{id} → Detalhe de um produto
POST /api/products → Criar (ADMIN)
PUT /api/products/{id} → Alterar (ADMIN)
DELETE /api/products/{id} → Remover (ADMIN)

Orders:
POST /api/orders → Realizar um pedido
GET /api/orders → Meus pedidos
GET /api/orders/{id} → Detalhe de um pedido
PATCH /api/orders/{id} → Alterar status (ADMIN)

Auth:
POST /api/auth/register → Cadastro
POST /api/auth/login → Login (retorna JWT)
POST /api/auth/refresh → Refresh do token

Cart:
GET /api/cart → Meu carrinho
POST /api/cart/items → Adicionar ao carrinho
DELETE /api/cart/items/{id} → Remover do carrinho

Q25. Sua aplicação Spring Boot está lenta em produção. Como você diagnostica?​

Resposta esperada:

  1. Métricas do Actuator : verificar /actuator/metrics/http.server.requests para identificar endpoints lentos
  2. Logs : ativar logging.level.org.hibernate.SQL=DEBUG para ver as queries SQL
  3. Problema N+1 : verificar o número de queries com spring.jpa.show-sql=true
  4. Connection pool : verificar métricas do HikariCP (hikaricp.connections.active)
  5. Profiling : VisualVM ou JFR (Java Flight Recorder)
  6. Índices no banco : analisar queries lentas com EXPLAIN ANALYZE
  7. Memória : verificar garbage collector e heap size

Checklist de Preparação​

Antes da sua entrevista, certifique-se de que você consegue:

  • Explicar IoC e DI com um exemplo concreto
  • Descrever a arquitetura em camadas de uma aplicação Spring Boot
  • Escrever um CRUD completo (Controller → Service → Repository)
  • Explicar JWT e o fluxo de autenticação
  • Falar sobre seus projetos pessoais com Spring Boot
  • Descrever como você trata exceções
  • Explicar a diferença entre as principais anotações
  • Falar sobre Docker e CI/CD com Spring Boot
  • Conhecer o básico de paginação e ordenação
  • Saber diagnosticar problemas de performance

⬅️ Voltar para o início