Capítulo 1: Anotaciones Core Spring
1. @SpringBootApplication
La anotación de arranque que combina tres anotaciones en una.
@SpringBootApplication
public class MonApplication {
public static void main(String[] args) {
SpringApplication.run(MonApplication.class, args);
}
}
Equivalente a:
@SpringBootConfiguration // Indica una clase de configuración
@EnableAutoConfiguration // Activa la autoconfiguración de Spring Boot
@ComponentScan // Escanea los componentes en el paquete actual y subpaquetes
2. Anotaciones de Estereotipo
Estas anotaciones identifican el rol de una clase en la arquitectura.
@Component
Anotación genérica para cualquier bean de Spring.
@Component
public class EmailValidator {
public boolean isValid(String email) {
return email != null && email.contains("@");
}
}
@Service
Indica una clase de lógica de negocio (capa de servicio).
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Usuario no encontrado"));
}
}
@Repository
Indica una clase de acceso a datos. Activa la traducción automática de excepciones SQL en excepciones de Spring.
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
}
@Controller
Indica un controlador MVC (retorna vistas HTML).
@Controller
public class PageController {
@GetMapping("/accueil")
public String accueil(Model model) {
model.addAttribute("message", "¡Bienvenido!");
return "accueil"; // Retorna el nombre de una vista (template)
}
}
@RestController
Combinación de @Controller + @ResponseBody. Cada método retorna JSON/XML directamente.
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping
public List<User> getAll() {
return userService.findAll(); // Retorna JSON automáticamente
}
}
Resumen de los estereotipos
| Anotación | Capa | Rol |
|---|---|---|
@Component | Genérica | Cualquier bean de Spring |
@Service | Servicio | Lógica de negocio |
@Repository | Datos | Acceso a base de datos |
@Controller | Web | Controlador MVC (vistas) |
@RestController | Web | Controlador REST (JSON) |
3. Anotaciones de Inyección de Dependencias
@Autowired
Inyección automática de un bean de Spring.
@Service
public class OrderService {
// Inyección por constructor (RECOMENDADO)
private final ProductService productService;
@Autowired // Opcional si solo hay un constructor
public OrderService(ProductService productService) {
this.productService = productService;
}
}
@Service
public class NotificationService {
// Inyección por campo (no recomendada pero frecuente)
@Autowired
private EmailService emailService;
// Inyección por setter
@Autowired
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
}
Prefiera siempre la inyección por constructor. Hace explícitas las dependencias y facilita las pruebas.
@Qualifier
Resuelve ambigüedades cuando varios beans implementan la misma interfaz.
public interface NotificationSender {
void send(String message);
}
@Component("emailSender")
public class EmailNotification implements NotificationSender {
public void send(String message) { /* envío de email */ }
}
@Component("smsSender")
public class SmsNotification implements NotificationSender {
public void send(String message) { /* envío de SMS */ }
}
@Service
public class AlertService {
private final NotificationSender sender;
public AlertService(@Qualifier("emailSender") NotificationSender sender) {
this.sender = sender;
}
}
@Primary
Define el bean por defecto cuando existen varios candidatos.
@Primary
@Component
public class EmailNotification implements NotificationSender {
// Este bean será inyectado por defecto
}
@Value
Inyecta valores desde los archivos de configuración.
@Service
public class AppConfig {
@Value("${app.name}")
private String appName;
@Value("${app.max-retry:3}") // Valor por defecto = 3
private int maxRetry;
@Value("${server.port}")
private int port;
@Value("#{2 + 3}") // SpEL (Spring Expression Language)
private int calculated;
}
# application.yml
app:
name: MonApplication
max-retry: 5
server:
port: 8080
@Lazy
Retrasa la inicialización del bean hasta su primer uso.
@Service
@Lazy
public class HeavyService {
public HeavyService() {
// Este constructor solo será llamado cuando el bean sea utilizado
}
}
4. Anotaciones de Configuración
@Configuration
Declara una clase de configuración de Spring (equivalente a XML).
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
return mapper;
}
}
@Bean
Declara un bean gestionado por el contenedor de Spring. Usado en clases @Configuration.
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authManager(AuthenticationConfiguration config)
throws Exception {
return config.getAuthenticationManager();
}
}
@ConfigurationProperties
Vincula un grupo de propiedades a un objeto Java.
@Configuration
@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
private String host;
private int port;
private String username;
private String password;
// Getters y setters obligatorios
public String getHost() { return host; }
public void setHost(String host) { this.host = host; }
// ...
}
# application.yml
app:
mail:
host: smtp.gmail.com
port: 587
username: user@gmail.com
password: secret
@PropertySource
Carga un archivo de propiedades adicional.
@Configuration
@PropertySource("classpath:custom-config.properties")
public class CustomConfig {
@Value("${custom.property}")
private String customProp;
}
@Import
Importa otras clases de configuración.
@Configuration
@Import({SecurityConfig.class, DatabaseConfig.class})
public class AppConfig {
}
5. Anotaciones de Ámbito y Ciclo de Vida
@Scope
Define el ámbito del bean.
@Component
@Scope("prototype") // Nueva instancia en cada inyección
public class ShoppingCart {
private List<Item> items = new ArrayList<>();
}
| Ámbito | Descripción |
|---|---|
singleton | Una sola instancia (por defecto) |
prototype | Nueva instancia en cada solicitud |
request | Una instancia por petición HTTP |
session | Una instancia por sesión HTTP |
application | Una instancia por ServletContext |
@PostConstruct
Ejecuta un método después de la inyección de todas las dependencias.
@Service
public class CacheService {
private Map<String, Object> cache;
@PostConstruct
public void init() {
cache = new HashMap<>();
// Cargar los datos iniciales
}
}
@PreDestroy
Ejecuta un método antes de la destrucción del bean.
@Service
public class ConnectionPool {
@PreDestroy
public void cleanup() {
// Cerrar todas las conexiones
}
}
6. Anotaciones de Perfil y Condiciones
@Profile
Activa un bean solo para ciertos perfiles.
@Configuration
@Profile("dev")
public class DevDatabaseConfig {
@Bean
public DataSource dataSource() {
// H2 en memoria para desarrollo
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
}
@Configuration
@Profile("prod")
public class ProdDatabaseConfig {
@Bean
public DataSource dataSource() {
// PostgreSQL para producción
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
return ds;
}
}
# Activar un perfil
java -jar app.jar --spring.profiles.active=prod
@ConditionalOnProperty
Activa un bean según el valor de una propiedad.
@Configuration
@ConditionalOnProperty(name = "app.feature.email", havingValue = "true")
public class EmailConfig {
@Bean
public EmailService emailService() {
return new SmtpEmailService();
}
}
@ConditionalOnClass
Activa un bean si una clase está presente en el classpath.
@Configuration
@ConditionalOnClass(name = "org.postgresql.Driver")
public class PostgresConfig {
// Configurado automáticamente si el driver de PostgreSQL está disponible
}
@ConditionalOnMissingBean
Activa un bean solo si no existe ningún otro bean del mismo tipo.
@Bean
@ConditionalOnMissingBean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
7. Anotaciones Lombok (Bonus)
Lombok genera código automáticamente en tiempo de compilación.
@Data
Genera getters, setters, toString, equals, hashCode.
@Data
public class UserDto {
private Long id;
private String name;
private String email;
}
@Getter / @Setter
@Getter @Setter
public class Product {
private Long id;
private String name;
private BigDecimal price;
}
@NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor
@NoArgsConstructor
@AllArgsConstructor
public class Address {
private String street;
private String city;
private String zipCode;
}
@RequiredArgsConstructor // Constructor para los campos final
@Service
public class UserService {
private final UserRepository userRepository; // Inyectado automáticamente
private final PasswordEncoder passwordEncoder;
}
@Builder
Implementa el patrón Builder.
@Builder
@Data
public class UserDto {
private Long id;
private String name;
private String email;
}
// Uso
UserDto user = UserDto.builder()
.id(1L)
.name("Jean")
.email("jean@example.com")
.build();
@Slf4j
Agrega un logger SLF4J automáticamente.
@Slf4j
@Service
public class PaymentService {
public void processPayment(Payment payment) {
log.info("Procesando el pago: {}", payment.getId());
log.debug("Monto: {}", payment.getAmount());
}
}
Resumen Rápido
| Anotación | Rol |
|---|---|
@SpringBootApplication | Punto de entrada de la aplicación |
@Component | Bean genérico |
@Service | Capa de servicio (lógica de negocio) |
@Repository | Capa de datos (acceso BDD) |
@Controller | Controlador MVC |
@RestController | Controlador REST |
@Autowired | Inyección de dependencia |
@Qualifier | Elección del bean a inyectar |
@Value | Inyección de valor de configuración |
@Configuration | Clase de configuración |
@Bean | Declaración manual de bean |
@ConfigurationProperties | Binding de propiedades |
@Profile | Activación por perfil |
@PostConstruct | Inicialización tras la inyección |
@PreDestroy | Limpieza antes de la destrucción |
➡️ Capítulo 2: Anotaciones Web y REST