Fundamentos de Spring Boot
En este capítulo aprenderemos cómo funciona Spring Boot internamente.
Entender esto es muy importante, porque es la base de todo lo que haremos después.
Veremos:
- qué es un Bean
- qué es la inyección de dependencias
- cómo funciona el contenedor de Spring
- las anotaciones más importantes
1. Qué es el contenedor de Spring #
El corazón de Spring es el contenedor de Spring.
El contenedor es el sistema que se encarga de:
- crear objetos
- gestionar dependencias
- conectar los objetos entre sí
- controlar su ciclo de vida
2. Sin Spring #
En Java tradicional el programador crea los objetos manualmente.
Ejemplo:
1UserRepository repository = new UserRepository(); 2UserService service = new UserService(repository);
El programador debe:
- crear objetos
- pasar dependencias
- gestionar todo manualmente
3. Con Spring #
Spring crea y conecta los objetos automáticamente.
1@Service 2public class UserService { 3 4 private final UserRepository repository; 5 6 public UserService(UserRepository repository) { 7 this.repository = repository; 8 } 9 10}
Spring detecta la dependencia y la inyecta automáticamente.
4. Qué es un Bean #
Un Bean es simplemente un objeto gestionado por Spring.
Cuando Spring crea un objeto y lo controla, ese objeto se llama Bean.
Ejemplos de Beans:
- controladores
- servicios
- repositorios
- componentes
5. Ejemplo de Bean #
1@Service 2public class UserService { 3 4}
Aquí UserService se convierte en un Bean.
Spring lo crea automáticamente cuando arranca la aplicación.
6. Inyección de dependencias #
La inyección de dependencias (Dependency Injection) es el mecanismo que usa Spring para conectar objetos.
La idea es simple:
Un objeto no crea sus dependencias.
Spring se las proporciona.
7. Ejemplo simple #
Repositorio:
1@Repository 2public class UserRepository { 3 4}
Servicio:
1@Service 2public class UserService { 3 4 private final UserRepository repository; 5 6 public UserService(UserRepository repository) { 7 this.repository = repository; 8 } 9 10}
Spring hace esto automáticamente:
1UserRepository repository = new UserRepository(); 2UserService service = new UserService(repository);
Pero sin que el programador tenga que hacerlo.
8. Por qué es importante la inyección de dependencias #
La inyección de dependencias tiene varias ventajas:
Código más limpio #
Los objetos no crean sus dependencias.
Código más fácil de probar #
En tests podemos sustituir dependencias fácilmente.
Menor acoplamiento #
Las clases dependen de interfaces o servicios, no de implementaciones concretas.
9. Anotaciones más importantes de Spring #
Spring usa anotaciones para indicar qué clases deben ser gestionadas.
Las más importantes son:
| anotación | función |
|---|---|
@Component | Bean genérico |
@Service | lógica de negocio |
@Repository | acceso a datos |
@Controller | controlador web |
@RestController | controlador REST |
10. @Component #
@Component es la anotación más básica.
Convierte una clase en un Bean de Spring.
Ejemplo:
1@Component 2public class EmailService { 3 4}
Spring crea automáticamente el objeto.
11. @Service #
@Service se usa para la lógica de negocio.
Ejemplo:
1@Service 2public class UserService { 3 4 public String getUserName() { 5 return "Ana"; 6 } 7 8}
12. @Repository #
@Repository se usa para acceso a base de datos.
Ejemplo:
1@Repository 2public class UserRepository { 3 4}
Normalmente se usa junto con Spring Data JPA.
13. @RestController #
@RestController define un controlador de API.
Ejemplo:
1@RestController 2public class HelloController { 3 4 @GetMapping("/hello") 5 public String hello() { 6 return "Hola mundo"; 7 } 8 9}
Spring automáticamente:
- detecta el controlador
- registra la ruta
/hello - devuelve la respuesta en JSON o texto
14. Flujo típico de una API #
Una aplicación Spring Boot suele seguir esta estructura:
Cliente → Controller → Service → Repository → Base de datos
15. Ejemplo completo #
Controller #
1@RestController 2public class UserController { 3 4 private final UserService service; 5 6 public UserController(UserService service) { 7 this.service = service; 8 } 9 10 @GetMapping("/user") 11 public String getUser() { 12 return service.getUserName(); 13 } 14 15}
Service #
1@Service 2public class UserService { 3 4 public String getUserName() { 5 return "Carlos"; 6 } 7 8}
Flujo #
- cliente llama a
/user - controller recibe petición
- controller llama al service
- service devuelve resultado
- controller devuelve respuesta
16. Qué hace @SpringBootApplication #
La anotación:
1@SpringBootApplication
es una combinación de tres anotaciones.
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
17. Qué hacen #
ComponentScan #
Busca clases con:
@Component
@Service
@Repository
@Controller
y las registra como Beans.
EnableAutoConfiguration #
Spring configura automáticamente:
- servidor web
- JSON
- base de datos
- seguridad
18. Escaneo de componentes #
Spring escanea automáticamente las clases dentro del mismo paquete.
Ejemplo:
com.example.demo
Si la clase principal está aquí:
DemoApplication
Spring escaneará:
com.example.demo.*
Por eso es importante organizar bien los paquetes.
19. Buenas prácticas #
Estructura recomendada:
controller
service
repository
entity
dto
config
Ejemplo:
com.example.app
controller
service
repository
entity
Resumen del tema
Conceptos clave #
- Contenedor de Inversión de Control (IoC Container / ApplicationContext): responsable de instanciar, configurar, enlazar y gestionar el ciclo de vida de los objetos (Beans).
- Inyección de Dependencias (DI): técnica para suministrar dependencias a componentes; la inyección por constructor es el estándar recomendado para garantizar inmutabilidad (
final) y testabilidad. - Estereotipos de Componentes:
@Component: bean genérico gestionado por el contenedor.@Service: capa de lógica de negocio y transacciones.@Repository: capa de acceso a datos y traducción de excepciones de persistencia.@RestController: capa web REST que combina@Controllery@ResponseBody.
- Flujo de Peticiones por Capas:
Cliente → Controller → Service → Repository → Base de Datos. - Mecanismo de
@SpringBootApplication: activa@Configuration,@EnableAutoConfigurationy@ComponentScanescaneando el paquete base y subpaquetes.
Qué debes recordar #
Usa inyección de dependencias por constructor con campos final y organiza tu código en capas estereotipadas (@RestController, @Service, @Repository) dentro del paquete raíz.