Top 10 Preguntas Esenciales de Spring
Las 10 Preguntas Más Importantes de Spring
Section titled “Las 10 Preguntas Más Importantes de Spring”Estas son las preguntas que siempre aparecen en entrevistas técnicas de Spring.
1. ¿Qué es Spring Framework y cuáles son sus módulos principales?
Section titled “1. ¿Qué es Spring Framework y cuáles son sus módulos principales?”Introducción: Pregunta de apertura en toda entrevista de Spring. Demuestra conocimiento general del ecosistema.
Definición profesional: Spring es un framework de Java que proporciona infraestructura completa para desarrollar aplicaciones empresariales. Su núcleo es el contenedor IoC (Inversión de Control) que gestiona el ciclo de vida de los objetos.
Explicación sencilla: Spring te ayuda a construir aplicaciones Java de forma más fácil: maneja la creación de objetos, conexiones a BD, seguridad, APIs REST, y mucho más.
Funcionamiento básico:
| Módulo | Descripción |
|---|---|
| Spring Core | IoC Container, Dependency Injection |
| Spring MVC | Framework web MVC |
| Spring Data | Acceso a datos (JPA, MongoDB, etc.) |
| Spring Security | Autenticación y autorización |
| Spring Boot | Configuración automática y arranque rápido |
| Spring Cloud | Microservicios y sistemas distribuidos |
Casos de uso reales:
- APIs REST empresariales
- Aplicaciones web con MVC
- Microservicios
- Integración con bases de datos
Cómo responder en entrevista:
“Spring es un framework de Java para aplicaciones empresariales. Su núcleo es el contenedor IoC que gestiona objetos mediante Dependency Injection. Los módulos principales son: Spring Core para DI, Spring MVC para web, Spring Data para acceso a datos, Spring Security para autenticación, Spring Boot para configuración automática, y Spring Cloud para microservicios.”
2. ¿Qué es Inversión de Control (IoC) y Dependency Injection (DI)?
Section titled “2. ¿Qué es Inversión de Control (IoC) y Dependency Injection (DI)?”Introducción: Conceptos fundamentales de Spring. Entenderlos es esencial para cualquier desarrollador Spring.
Definición profesional: IoC (Inversión de Control) es un principio donde el framework controla el flujo del programa y la creación de objetos. DI (Dependency Injection) es el patrón que implementa IoC, donde las dependencias se “inyectan” desde fuera en vez de crearse internamente.
Explicación sencilla:
- Sin DI: Tu clase crea sus propias dependencias (acoplado)
- Con DI: Alguien más (Spring) te da las dependencias que necesitas (desacoplado)
Funcionamiento básico:
| Tipo de Inyección | Uso | Recomendación |
|---|---|---|
| Constructor | Dependencias obligatorias | ✅ Preferido |
| Setter | Dependencias opcionales | ⚠️ Ocasional |
| Field (@Autowired) | Rápido pero acoplado | ❌ Evitar |
Ejemplo práctico:
// ❌ SIN Dependency Injection (acoplado)public class ServicioUsuario { private RepositorioUsuario repo = new RepositorioUsuarioImpl(); // Problema: no puedes cambiar la implementación ni testear fácilmente}
// ✅ CON Dependency Injection (desacoplado)@Servicepublic class ServicioUsuario { private final RepositorioUsuario repo;
// Constructor Injection - Spring inyecta automáticamente public ServicioUsuario(RepositorioUsuario repo) { this.repo = repo; }
public Usuario buscar(Long id) { return repo.findById(id); }}
// En tests puedes inyectar un mock fácilmente:// new ServicioUsuario(mockRepository)Casos de uso reales:
- Inyectar repositorios en servicios
- Inyectar servicios en controladores
- Facilitar testing con mocks
Cómo responder en entrevista:
“IoC es el principio donde el framework controla la creación y ciclo de vida de los objetos. DI es el patrón que implementa IoC, donde las dependencias se inyectan desde fuera. En Spring, usamos anotaciones como @Service y @Autowired. La forma recomendada es Constructor Injection porque hace las dependencias explícitas, permite inmutabilidad con final, y facilita el testing.”
3. ¿Qué es un Bean en Spring?
Section titled “3. ¿Qué es un Bean en Spring?”Introducción: Concepto central de Spring. Todo en Spring gira alrededor de los Beans.
Definición profesional: Un Bean es un objeto cuyo ciclo de vida es gestionado por el contenedor IoC de Spring. Spring se encarga de crear, configurar, inyectar dependencias y destruir estos objetos.
Explicación sencilla: Es cualquier objeto que Spring conoce y maneja por ti. Tú defines qué es un Bean, Spring se encarga del resto.
Funcionamiento básico:
| Anotación | Capa | Uso |
|---|---|---|
@Component | Genérico | Cualquier componente |
@Service | Negocio | Lógica de negocio |
@Repository | Datos | Acceso a BD |
@Controller | Web | Controladores MVC |
@RestController | Web | APIs REST |
Ejemplo práctico:
// Forma 1: Anotaciones de estereotipo@Servicepublic class UsuarioService { // Spring lo detecta y gestiona automáticamente}
// Forma 2: @Bean en clase @Configuration@Configurationpublic class AppConfig {
@Bean public RestTemplate restTemplate() { return new RestTemplate(); }
@Bean public ObjectMapper objectMapper() { return new ObjectMapper() .registerModule(new JavaTimeModule()); }}Casos de uso reales:
- Servicios de negocio (@Service)
- Repositorios de datos (@Repository)
- Configuraciones externas (@Bean)
- Clientes HTTP, ObjectMapper, etc.
Cómo responder en entrevista:
“Un Bean es un objeto gestionado por el contenedor IoC de Spring. Se pueden definir con anotaciones de estereotipo como @Component, @Service, @Repository, o con @Bean en clases @Configuration. Spring se encarga de instanciarlos, inyectar sus dependencias, y gestionar su ciclo de vida.”
4. ¿Cuáles son los scopes de un Bean?
Section titled “4. ¿Cuáles son los scopes de un Bean?”Introducción: Define cuántas instancias de un Bean existen y cuánto tiempo viven.
Definición profesional: El scope de un Bean determina el ciclo de vida y visibilidad de las instancias. El scope por defecto es singleton (una instancia por contenedor).
Explicación sencilla:
- Singleton: Un solo objeto compartido por todos
- Prototype: Un objeto nuevo cada vez que lo pides
Funcionamiento básico:
| Scope | Instancias | Uso |
|---|---|---|
singleton | 1 por contenedor | Default, stateless |
prototype | Nueva cada vez | Stateful, no compartir |
request | 1 por HTTP request | Web, datos de request |
session | 1 por sesión HTTP | Web, datos de usuario |
Ejemplo práctico:
// Singleton (default) - una instancia compartida@Servicepublic class UsuarioService { // Todos usan la misma instancia}
// Prototype - nueva instancia cada vez@Component@Scope("prototype")public class ReporteGenerator { private List<String> datos = new ArrayList<>(); // Cada inyección crea una nueva instancia}
// Request scope - una por request HTTP@Component@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)public class RequestContext { private String userId;}Casos de uso reales:
- Singleton: Servicios, repositorios, configuraciones
- Prototype: Objetos con estado, builders
- Request: Contexto del request actual
Cómo responder en entrevista:
“El scope define cuántas instancias de un Bean existen. El default es singleton: una instancia por contenedor, ideal para servicios stateless. Prototype crea una nueva instancia cada vez, útil para objetos con estado. En aplicaciones web también hay request y session scope. Es importante que los singletons sean thread-safe.”
5. ¿Qué es Spring Boot y qué ventajas ofrece?
Section titled “5. ¿Qué es Spring Boot y qué ventajas ofrece?”Introducción: Spring Boot es la forma moderna de desarrollar con Spring. Elimina la configuración manual.
Definición profesional: Spring Boot es un proyecto de Spring que simplifica la creación de aplicaciones mediante auto-configuración, servidores embebidos, y convención sobre configuración.
Explicación sencilla: Spring Boot = Spring sin dolor. Configura todo automáticamente para que puedas enfocarte en el código de negocio.
Funcionamiento básico:
| Característica | Beneficio |
|---|---|
| Auto-configuración | Configura según dependencias |
| Starters | Dependencias pre-empaquetadas |
| Embedded Server | Tomcat/Jetty incluido |
| Actuator | Monitoreo y métricas |
| DevTools | Hot reload en desarrollo |
Ejemplo práctico:
// Aplicación completa en una clase@SpringBootApplicationpublic class MiAplicacion { public static void main(String[] args) { SpringApplication.run(MiAplicacion.class, args); }}
// @SpringBootApplication =// @Configuration + @EnableAutoConfiguration + @ComponentScan
// application.yml - configuración simple// server:// port: 8080// spring:// datasource:// url: jdbc:postgresql://localhost/db// username: user// password: passCasos de uso reales:
- APIs REST
- Microservicios
- Aplicaciones web
- Batch processing
Cómo responder en entrevista:
“Spring Boot simplifica el desarrollo con Spring mediante auto-configuración, starters de dependencias, y servidores embebidos. Con @SpringBootApplication puedes tener una aplicación corriendo en minutos. Incluye Actuator para monitoreo y DevTools para desarrollo. La filosofía es convención sobre configuración: funciona out-of-the-box y solo configuras lo que necesitas cambiar.”
6. ¿Cómo crear un REST Controller en Spring?
Section titled “6. ¿Cómo crear un REST Controller en Spring?”Introducción: Pregunta práctica esencial. Demuestra conocimiento de Spring MVC y APIs REST.
Definición profesional:
Un REST Controller es un componente que maneja requests HTTP y retorna respuestas (generalmente JSON). Se crea con @RestController que combina @Controller + @ResponseBody.
Explicación sencilla: Es donde defines los endpoints de tu API: qué URL responde a qué método y qué datos retorna.
Funcionamiento básico:
| Anotación | Método HTTP | Uso |
|---|---|---|
@GetMapping | GET | Obtener datos |
@PostMapping | POST | Crear recurso |
@PutMapping | PUT | Actualizar completo |
@PatchMapping | PATCH | Actualizar parcial |
@DeleteMapping | DELETE | Eliminar |
Ejemplo práctico:
@RestController@RequestMapping("/api/usuarios")public class UsuarioController {
private final UsuarioService service;
public UsuarioController(UsuarioService service) { this.service = service; }
@GetMapping public List<Usuario> listar() { return service.findAll(); }
@GetMapping("/{id}") public ResponseEntity<Usuario> buscar(@PathVariable Long id) { return service.findById(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); }
@PostMapping @ResponseStatus(HttpStatus.CREATED) public Usuario crear(@RequestBody @Valid UsuarioDTO dto) { return service.save(dto); }
@DeleteMapping("/{id}") @ResponseStatus(HttpStatus.NO_CONTENT) public void eliminar(@PathVariable Long id) { service.delete(id); }}Casos de uso reales:
- APIs para frontend (React, Angular)
- Microservicios
- Integraciones con terceros
Cómo responder en entrevista:
“Un REST Controller se crea con @RestController y @RequestMapping para definir la URL base. Uso @GetMapping, @PostMapping, etc. para los métodos HTTP. @PathVariable extrae valores de la URL, @RequestBody deserializa el JSON del body, y @Valid activa validaciones. ResponseEntity permite controlar el status code y headers de la respuesta.”
7. ¿Qué es Spring Data JPA?
Section titled “7. ¿Qué es Spring Data JPA?”Introducción: Simplifica enormemente el acceso a datos. Elimina el boilerplate de JPA/Hibernate.
Definición profesional: Spring Data JPA es un módulo que simplifica la implementación de repositorios JPA. Genera automáticamente las implementaciones de los métodos de acceso a datos basándose en convenciones de nombres.
Explicación sencilla:
Defines una interfaz con métodos como findByNombre(), y Spring genera automáticamente el SQL y la implementación.
Funcionamiento básico:
| Método | SQL Generado |
|---|---|
findByNombre(String) | WHERE nombre = ? |
findByEdadGreaterThan(int) | WHERE edad > ? |
findByActivoTrue() | WHERE activo = true |
findByNombreContaining(String) | WHERE nombre LIKE %?% |
Ejemplo práctico:
// Entidad JPA@Entity@Table(name = "usuarios")public class Usuario { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
private String nombre;
@Column(unique = true) private String email;}
// Repository - Spring genera la implementación automáticamentepublic interface UsuarioRepository extends JpaRepository<Usuario, Long> {
// Query methods - Spring genera el SQL Optional<Usuario> findByEmail(String email); List<Usuario> findByNombreContaining(String nombre); List<Usuario> findByActivoTrueOrderByNombreAsc();
// Query personalizada con JPQL @Query("SELECT u FROM Usuario u WHERE u.rol = :rol") List<Usuario> findByRol(@Param("rol") String rol);
// Query nativa @Query(value = "SELECT * FROM usuarios WHERE created_at > ?1", nativeQuery = true) List<Usuario> findRecientes(LocalDate fecha);}Casos de uso reales:
- CRUD de entidades
- Búsquedas complejas
- Paginación y ordenamiento
- Auditoría automática
Cómo responder en entrevista:
“Spring Data JPA simplifica el acceso a datos generando automáticamente la implementación de repositorios. Solo defino una interfaz que extiende JpaRepository y uso query methods como findByNombre() que Spring convierte a SQL. Para queries complejas uso @Query con JPQL o SQL nativo. También soporta paginación con Pageable y especificaciones para queries dinámicas.”
8. ¿Qué es @Transactional?
Section titled “8. ¿Qué es @Transactional?”Introducción: Esencial para operaciones de base de datos. Garantiza consistencia de datos.
Definición profesional:
@Transactional es una anotación que gestiona transacciones de base de datos declarativamente. Si el método falla, hace rollback automático; si termina exitosamente, hace commit.
Explicación sencilla: “Todo o nada”: si algo falla dentro del método, todos los cambios a la BD se revierten automáticamente.
Funcionamiento básico:
| Atributo | Descripción |
|---|---|
readOnly | Optimiza lecturas, no permite escrituras |
rollbackFor | Excepciones que causan rollback |
propagation | Cómo se comporta con transacciones existentes |
isolation | Nivel de aislamiento |
Ejemplo práctico:
@Servicepublic class TransferenciaService {
private final CuentaRepository cuentaRepo;
@Transactional // Rollback automático si falla public void transferir(Long origenId, Long destinoId, BigDecimal monto) { Cuenta origen = cuentaRepo.findById(origenId) .orElseThrow(() -> new CuentaNoEncontradaException()); Cuenta destino = cuentaRepo.findById(destinoId) .orElseThrow(() -> new CuentaNoEncontradaException());
origen.debitar(monto); destino.acreditar(monto);
cuentaRepo.save(origen); cuentaRepo.save(destino); // Si falla aquí, AMBAS operaciones se revierten }
@Transactional(readOnly = true) // Optimización para lecturas public List<Cuenta> listar() { return cuentaRepo.findAll(); }}Casos de uso reales:
- Transferencias bancarias
- Operaciones que modifican múltiples tablas
- Cualquier operación que requiera atomicidad
Cómo responder en entrevista:
“@Transactional gestiona transacciones declarativamente. Si el método termina exitosamente hace commit, si lanza una excepción hace rollback. Por defecto solo hace rollback en RuntimeExceptions. Uso readOnly=true para optimizar lecturas. Es importante que el método sea público y llamado desde fuera de la clase para que el proxy de Spring funcione.”
9. ¿Qué es Spring Security?
Section titled “9. ¿Qué es Spring Security?”Introducción: Framework de seguridad estándar para aplicaciones Spring. Maneja autenticación y autorización.
Definición profesional: Spring Security es un framework que proporciona autenticación (quién eres), autorización (qué puedes hacer), y protección contra ataques comunes (CSRF, XSS, etc.).
Explicación sencilla:
- Autenticación: Verificar que eres quien dices ser (login)
- Autorización: Verificar que tienes permiso para hacer algo (roles)
Funcionamiento básico:
| Concepto | Descripción |
|---|---|
Authentication | Representa al usuario autenticado |
Authorization | Permisos y roles del usuario |
SecurityFilterChain | Cadena de filtros de seguridad |
UserDetailsService | Carga datos del usuario |
Ejemplo práctico:
@Configuration@EnableWebSecuritypublic class SecurityConfig {
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .csrf(csrf -> csrf.disable()) // Deshabilitar para APIs REST .authorizeHttpRequests(auth -> auth .requestMatchers("/api/public/**").permitAll() .requestMatchers("/api/admin/**").hasRole("ADMIN") .requestMatchers("/api/**").authenticated() ) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) .httpBasic(Customizer.withDefaults()) .build(); }
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }}Casos de uso reales:
- Autenticación con JWT
- Control de acceso por roles
- OAuth2 / OpenID Connect
- Protección de APIs REST
Cómo responder en entrevista:
“Spring Security maneja autenticación y autorización. La configuración moderna usa SecurityFilterChain para definir reglas de acceso. Uso requestMatchers para definir qué endpoints son públicos, cuáles requieren autenticación, y cuáles requieren roles específicos. Para APIs REST típicamente deshabilito CSRF y uso sesiones stateless con JWT.”
10. ¿Cómo manejar excepciones en Spring?
Section titled “10. ¿Cómo manejar excepciones en Spring?”Introducción: Tema práctico importante. Un buen manejo de errores mejora la experiencia del API.
Definición profesional:
Spring permite manejar excepciones de forma centralizada usando @RestControllerAdvice y @ExceptionHandler, convirtiendo excepciones en respuestas HTTP apropiadas.
Explicación sencilla: En lugar de try-catch en cada controlador, defines un manejador global que captura excepciones y retorna respuestas de error consistentes.
Funcionamiento básico:
| Anotación | Uso |
|---|---|
@RestControllerAdvice | Clase que maneja excepciones globalmente |
@ExceptionHandler | Método que maneja un tipo de excepción |
@ResponseStatus | Define el código HTTP de respuesta |
Ejemplo práctico:
// Excepción personalizadapublic class UsuarioNoEncontradoException extends RuntimeException { public UsuarioNoEncontradoException(Long id) { super("Usuario no encontrado: " + id); }}
// Manejador global de excepciones@RestControllerAdvicepublic class GlobalExceptionHandler {
@ExceptionHandler(UsuarioNoEncontradoException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public ErrorResponse handleNotFound(UsuarioNoEncontradoException ex) { return new ErrorResponse(404, ex.getMessage()); }
@ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorResponse handleValidation(MethodArgumentNotValidException ex) { List<String> errores = ex.getBindingResult() .getFieldErrors() .stream() .map(e -> e.getField() + ": " + e.getDefaultMessage()) .toList(); return new ErrorResponse(400, "Validación fallida", errores); }
@ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ErrorResponse handleGeneral(Exception ex) { return new ErrorResponse(500, "Error interno"); }}
// DTO de respuesta de errorpublic record ErrorResponse(int status, String mensaje, Object... detalles) {}Casos de uso reales:
- Recursos no encontrados (404)
- Errores de validación (400)
- Errores de autenticación (401/403)
- Errores internos (500)
Cómo responder en entrevista:
“Uso @RestControllerAdvice para manejar excepciones globalmente. Defino métodos con @ExceptionHandler para cada tipo de excepción, retornando un DTO de error consistente con el código HTTP apropiado. Esto centraliza el manejo de errores y garantiza respuestas uniformes en toda la API. También manejo MethodArgumentNotValidException para errores de validación de @Valid.”