Saltar al contenido principal

Módulo 18: Preguntas de Entrevista Spring Boot

Objetivos​

Este módulo le prepara para las entrevistas técnicas en desarrollo Java/Spring Boot. Las preguntas están organizadas por nivel de dificultad y por tema, cubriendo los temas más frecuentemente preguntados en entrevistas.

Consejo

No memorice las respuestas palabra por palabra. Comprenda los conceptos y sea capaz de explicarlos con sus propias palabras y ejemplos concretos.


Capítulos del Módulo​

#CapítuloContenido
1JPA & Base de DatosProblema N+1, Lazy/Eager loading, @Transactional, paginación, relaciones entre entidades
2Ejercicios de RefactorizaciónGuard clauses, Strategy Pattern, SRP (God Class), constantes mágicas, composición vs herencia
3Algoritmos & Estructuras de DatosHashMap, Stack, LinkedList, Binary Search, Two Sum, FizzBuzz, anagramas
4Diseño REST & Design PatternsAPI REST, Builder, Singleton, Observer con Spring Events
5Depuración & Revisión de CódigoEncontrar bugs, revisión de código, fuga de memoria, concurrencia, excepciones, code smells
6Trampas Fundamentales de Java== vs .equals(), hashCode(), final, static, String inmutable, Optional, paso por valor
7Colecciones JavaList.of() vs new ArrayList<>(), HashMap, HashSet, Stream API, thread-safety, iteración
8"¿Qué es...?" — 30 conceptosDTO, MVC, API REST, CRUD, POJO, Bean, IoC, ORM/JPA, Maven, Docker, JWT, CORS, Lombok, Record...

Nivel 1 : Preguntas Fundamentales​

Q1. ¿Qué es Spring Boot y en qué se diferencia de Spring Framework?​

Respuesta esperada:

Spring Boot es un framework construido encima de Spring Framework que simplifica la configuración y el despliegue. Las diferencias principales:

AspectoSpring FrameworkSpring Boot
ConfiguraciónManual (XML o Java)Auto-configuración
ServidorRequiere servidor externoServidor embebido (Tomcat)
DependenciasGestionadas individualmenteStarters preconfigurados
ArranqueComplejomain() + @SpringBootApplication

Spring Boot no reemplaza Spring, lo hace más fácil de usar.


Q2. ¿Qué hace la anotación @SpringBootApplication?​

Respuesta esperada:

Es una meta-anotación que combina tres anotaciones:

  • @SpringBootConfiguration : indica una clase de configuración Spring
  • @EnableAutoConfiguration : activa la auto-configuración basada en las dependencias del classpath
  • @ComponentScan : escanea el paquete actual y sus subpaquetes para encontrar los beans

Q3. ¿Qué es la inyección de dependencias (DI)?​

Respuesta esperada:

La inyección de dependencias es un patrón de diseño donde las dependencias de un objeto son proporcionadas desde el exterior en lugar de ser creadas por el propio objeto.

// SIN DI (acoplamiento fuerte)
public class OrderService {
private UserRepository repo = new UserRepository(); // Crea su propia dependencia
}

// CON DI (acoplamiento débil)
public class OrderService {
private final UserRepository repo;

public OrderService(UserRepository repo) { // Inyectada desde el exterior
this.repo = repo;
}
}

Ventajas: testabilidad, desacoplamiento, flexibilidad.


Q4. ¿Cuál es la diferencia entre @Controller y @RestController?​

Respuesta esperada:

  • @Controller retorna nombres de vistas (plantillas HTML). Para retornar JSON, se debe añadir @ResponseBody en cada método.
  • @RestController = @Controller + @ResponseBody. Cada método retorna directamente datos serializados en JSON.

Q5. ¿Cuáles son los diferentes ámbitos de bean en Spring?​

Respuesta esperada:

ÁmbitoDescripción
singletonUna sola instancia por contenedor (por defecto)
prototypeNueva instancia en cada inyección
requestUna instancia por petición HTTP
sessionUna instancia por sesión HTTP
applicationUna instancia por ServletContext

Q6. ¿Cuál es la diferencia entre application.properties y application.yml?​

Respuesta esperada:

Misma funcionalidad, sintaxis diferente:

# application.properties (clave=valor, plano)
server.port=8080
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
# application.yml (jerárquico, más legible)
server:
port: 8080
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb

YAML es más legible para configuraciones anidadas, pero cuidado con la indentación.


Q7. ¿Qué es un Starter Spring Boot?​

Respuesta esperada:

Un starter es un conjunto de dependencias preconfiguradas para un uso específico:

  • spring-boot-starter-web : aplicación web (Tomcat, Spring MVC, Jackson)
  • spring-boot-starter-data-jpa : persistencia (Hibernate, Spring Data JPA)
  • spring-boot-starter-security : seguridad (Spring Security)
  • spring-boot-starter-test : pruebas (JUnit, Mockito, MockMvc)

Evitan gestionar manualmente las compatibilidades entre versiones.


Nivel 2 : Preguntas Intermedias​

Q8. Explique la arquitectura en capas de una aplicación Spring Boot.​

Respuesta esperada:

Cliente HTTP
↓
┌─────────────────┐
│ Controller │ Recibe las peticiones, valida, retorna las respuestas
├─────────────────┤
│ Service │ Lógica de negocio, reglas de negocio, orquestación
├─────────────────┤
│ Repository │ Acceso a datos (CRUD, consultas BDD)
├─────────────────┤
│ Database │ PostgreSQL, MySQL, H2...
└─────────────────┘

Cada capa solo se comunica con la capa directamente inferior. El Controller nunca accede directamente al Repository.


Q9. ¿Cuál es la diferencia entre JpaRepository, CrudRepository y PagingAndSortingRepository?​

Respuesta esperada:

JpaRepository (el más completo)
↑ hereda de
PagingAndSortingRepository (paginación + orden)
↑ hereda de
CrudRepository (CRUD básico)
↑ hereda de
Repository (marcador)
  • CrudRepository : save(), findById(), findAll(), deleteById()
  • PagingAndSortingRepository : añade findAll(Pageable), findAll(Sort)
  • JpaRepository : añade flush(), saveAndFlush(), deleteInBatch(), retorna List en vez de Iterable

En la práctica, casi siempre se utiliza JpaRepository.


Q10. ¿Cómo funciona la auto-configuración en Spring Boot?​

Respuesta esperada:

Spring Boot examina el classpath al arrancar y configura automáticamente los beans necesarios:

  1. Si spring-boot-starter-data-jpa está en el classpath Y hay una DataSource configurada → auto-configura Hibernate, EntityManager, etc.
  2. Si spring-boot-starter-web está en el classpath → auto-configura Tomcat, Jackson, DispatcherServlet
  3. Las anotaciones @ConditionalOn... determinan si una auto-configuración se aplica

Siempre se pueden sobrescribir los beans auto-configurados con nuestros propios @Bean.


Q11. ¿Qué son los Spring Profiles y para qué sirven?​

Respuesta esperada:

Los profiles permiten cargar configuraciones diferentes según el entorno:

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

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

Activación: --spring.profiles.active=prod o SPRING_PROFILES_ACTIVE=prod

También se pueden condicionar beans con @Profile("dev").


Q12. Explique la diferencia entre @Transactional de solo lectura y de escritura.​

Respuesta esperada:

@Transactional(readOnly = true)   // Lectura: optimización Hibernate (sin dirty checking)
public List<User> findAll() { ... }

@Transactional // Escritura: commit si éxito, rollback si excepción
public User create(UserDto dto) { ... }

Buena práctica: Poner @Transactional(readOnly = true) a nivel de la clase de servicio, y @Transactional solo en los métodos de escritura.


Q13. ¿Cómo se gestionan las excepciones en una API REST Spring Boot?​

Respuesta esperada:

Tres enfoques, del más local al más global:

  1. @ExceptionHandler en un controlador (alcance local)
  2. @RestControllerAdvice con @ExceptionHandler (alcance global)
  3. @ResponseStatus en una excepción personalizada

La mejor práctica es el @RestControllerAdvice global que centraliza toda la gestión de errores.


Q14. ¿Qué es el problema N+1 en JPA y cómo se resuelve?​

Respuesta esperada:

El problema N+1 ocurre cuando se carga una entidad y JPA ejecuta N consultas adicionales para cargar las relaciones:

1 consulta para cargar 100 departamentos
+ 100 consultas para cargar los empleados de cada departamento
= 101 consultas en vez de 1 o 2

Soluciones:

  • JOIN FETCH en JPQL : @Query("SELECT d FROM Department d JOIN FETCH d.employees")
  • @EntityGraph : @EntityGraph(attributePaths = {"employees"})
  • @BatchSize : carga las relaciones por lotes

Q15. ¿Cómo se securiza una API REST con JWT?​

Respuesta esperada:

El flujo JWT:

1. El cliente envía login/password → POST /api/auth/login
2. El servidor verifica las credenciales
3. Si OK → genera un JWT firmado y lo retorna
4. El cliente almacena el JWT
5. Para cada petición → Authorization: Bearer <token>
6. JwtAuthenticationFilter extrae y valida el token
7. Si es válido → autentica al usuario en el SecurityContext

Componentes clave: JwtService (generación/validación), JwtAuthenticationFilter (filtro), SecurityConfig (configuración).


Nivel 3 : Preguntas Avanzadas​

Q16. Explique el patrón IoC (Inversión de Control) en Spring.​

Respuesta esperada:

IoC invierte el flujo de control: en vez de que el código cree sus dependencias, el contenedor Spring las crea y las inyecta.

El contenedor Spring (ApplicationContext) es responsable de:

  1. Crear los objetos (beans)
  2. Configurar los objetos
  3. Ensamblar las dependencias
  4. Gestionar el ciclo de vida

La inyección de dependencias (DI) es el mecanismo principal de IoC en Spring.


Q17. ¿Cuál es la diferencia entre @Component, @Service, @Repository y @Controller?​

Respuesta esperada:

Técnicamente, las cuatro son @Component. La diferencia es semántica (rol en la arquitectura):

  • @Component : bean genérico
  • @Service : lógica de negocio
  • @Repository : acceso a datos + traducción automática de excepciones SQL en excepciones Spring
  • @Controller : gestión de peticiones web

Usar la anotación correcta ayuda a la legibilidad y permite tratamientos específicos (ej: traducción de excepciones para @Repository).


Q18. ¿Cómo implementar la paginación en Spring Data JPA?​

Respuesta 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);
}

El Page<T> retornado contiene: contenido, número de página, tamaño, total de elementos, número de páginas.


Q19. Explique las diferentes estrategias de propagación de @Transactional.​

Respuesta esperada:

PropagaciónComportamiento
REQUIRED (por defecto)Se une a la transacción existente o crea una nueva
REQUIRES_NEWSiempre crea una nueva transacción (suspende la existente)
SUPPORTSSe une si existe, si no ejecuta sin transacción
NOT_SUPPORTEDSiempre ejecuta sin transacción (suspende la existente)
MANDATORYRequiere transacción existente, si no lanza excepción
NEVERSin transacción, si hay una lanza excepción
NESTEDTransacción anidada (savepoint)

Caso de uso frecuente de REQUIRES_NEW: log de auditoría que debe persistir incluso si la transacción principal falla.


Q20. ¿Cómo optimizar el rendimiento de una aplicación Spring Boot?​

Respuesta esperada:

  1. JPA/Hibernate:

    • Evitar el problema N+1 (JOIN FETCH, EntityGraph)
    • Usar @Transactional(readOnly = true) para lecturas
    • Proyecciones DTO en vez de entidades completas
    • Paginación sistemática
  2. Cache:

    • @Cacheable con Spring Cache (Redis, Caffeine)
    • Cache HTTP (ETag, Cache-Control)
  3. Configuración:

    • Connection pooling (HikariCP bien configurado)
    • Compresión GZIP
    • Perfiles optimizados para producción
  4. Arquitectura:

    • Operaciones asíncronas (@Async)
    • Indexación adecuada en la BDD
    • Lazy loading de relaciones

Q21. ¿Qué es Spring Actuator y qué endpoints útiles proporciona?​

Respuesta esperada:

Spring Actuator proporciona endpoints de monitoreo y gestión:

EndpointDescripción
/actuator/healthEstado de la aplicación (UP/DOWN)
/actuator/infoInformación sobre la aplicación
/actuator/metricsMétricas (memoria, CPU, peticiones)
/actuator/envVariables de entorno
/actuator/beansLista de todos los beans
/actuator/mappingsTodos los endpoints REST
/actuator/loggersConfiguración de loggers
/actuator/prometheusMétricas en formato Prometheus

En producción, se deben securizar estos endpoints y exponer solo /health y /info públicamente.


Q22. Explique el ciclo de vida de un bean Spring.​

Respuesta esperada:

1. Instanciación (constructor)
2. Inyección de dependencias (@Autowired)
3. Aware interfaces (BeanNameAware, ApplicationContextAware...)
4. BeanPostProcessor.postProcessBeforeInitialization()
5. @PostConstruct
6. InitializingBean.afterPropertiesSet()
7. init-method personalizado
8. BeanPostProcessor.postProcessAfterInitialization()
9. ══════ Bean listo para usar ══════
10. @PreDestroy
11. DisposableBean.destroy()
12. destroy-method personalizado

En la práctica, se usan sobre todo @PostConstruct y @PreDestroy.


Q23. ¿Cómo implementar un patrón CQRS simplificado con Spring Boot?​

Respuesta esperada:

CQRS (Command Query Responsibility Segregation) separa las operaciones de lectura y escritura:

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

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

Esto permite optimizar las lecturas y escrituras por separado (ej: proyecciones DTO para lecturas, validaciones complejas para escrituras).


Preguntas Conductuales / Escenarios​

Q24. Debe diseñar una API REST para un sistema de e-commerce. ¿Qué endpoints crea?​

Respuesta esperada:

Products:
GET /api/products → Lista paginada
GET /api/products/{id} → Detalle de un producto
POST /api/products → Crear (ADMIN)
PUT /api/products/{id} → Modificar (ADMIN)
DELETE /api/products/{id} → Eliminar (ADMIN)

Orders:
POST /api/orders → Realizar un pedido
GET /api/orders → Mis pedidos
GET /api/orders/{id} → Detalle de un pedido
PATCH /api/orders/{id} → Modificar estado (ADMIN)

Auth:
POST /api/auth/register → Registro
POST /api/auth/login → Login (retorna JWT)
POST /api/auth/refresh → Refrescar el token

Cart:
GET /api/cart → Mi carrito
POST /api/cart/items → Añadir al carrito
DELETE /api/cart/items/{id} → Quitar del carrito

Q25. Su aplicación Spring Boot es lenta en producción. ¿Cómo lo diagnostica?​

Respuesta esperada:

  1. Actuator metrics : verificar /actuator/metrics/http.server.requests para identificar los endpoints lentos
  2. Logs : activar logging.level.org.hibernate.SQL=DEBUG para ver las consultas SQL
  3. Problema N+1 : verificar el número de consultas con spring.jpa.show-sql=true
  4. Connection pool : verificar las métricas de HikariCP (hikaricp.connections.active)
  5. Profiling : VisualVM o JFR (Java Flight Recorder)
  6. Índices BDD : analizar las consultas lentas con EXPLAIN ANALYZE
  7. Memoria : verificar el garbage collector y el heap size

Checklist de Preparación​

Antes de su entrevista, asegúrese de poder:

  • Explicar IoC y DI con un ejemplo concreto
  • Describir la arquitectura en capas de una app Spring Boot
  • Escribir un CRUD completo (Controller → Service → Repository)
  • Explicar JWT y el flujo de autenticación
  • Hablar de sus proyectos personales con Spring Boot
  • Describir cómo gestiona las excepciones
  • Explicar la diferencia entre las anotaciones clave
  • Hablar de Docker y CI/CD con Spring Boot
  • Conocer lo básico de paginación y orden
  • Saber diagnosticar problemas de rendimiento

⬅️ Volver al inicio