Skip to main content

Command Palette

Search for a command to run...

Jakarta Annotations en Quarkus: Gestión del Ciclo de Vida y Anotaciones Personalizadas

Updated
4 min read

Introducción

Jakarta Annotations proporciona anotaciones estándar para gestionar el ciclo de vida de componentes y crear anotaciones personalizadas. En Quarkus, estas anotaciones están completamente soportadas y funcionan de forma integrada con CDI.

¿Qué son las Anotaciones?

Las anotaciones en Java son metadatos que se pueden agregar a clases, métodos, campos y otros elementos del código. Jakarta EE define varias anotaciones estándar para gestionar el ciclo de vida y comportamiento de los componentes.

Anotaciones Estándar de Jakarta

@PostConstruct

Se ejecuta después de que el bean ha sido construido e inyectado:

@ApplicationScoped
public class HeroService {

    @PostConstruct
    public void init() {
        // Se ejecuta después de la construcción
        // Útil para inicialización
        logger.info("HeroService initialized");
    }
}

@PreDestroy

Se ejecuta antes de que el bean sea destruido:

@ApplicationScoped
public class HeroService {

    @PreDestroy
    public void cleanup() {
        // Se ejecuta antes de la destrucción
        // Útil para liberar recursos
        logger.info("HeroService cleaning up");
    }
}

@Resource

Inyecta recursos del contenedor:

@ApplicationScoped
public class HeroService {

    @Resource
    private Logger logger;

    @Resource(name = "jdbc/heroesDB")
    private DataSource dataSource;
}

@Generated

Marca código generado automáticamente:

@Generated(value = "code-generator", date = "2024-01-01")
public class GeneratedHero {
    // Código generado
}

Anotaciones Personalizadas

Crear una Anotación Personalizada

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface HeroPower {
    int minLevel() default 1;
    String description() default "";
}

Usar la Anotación

@HeroPower(minLevel = 80, description = "Héroe poderoso")
@Loggable(level = "INFO")
public void activateHero(String name) {
    // Método marcado con anotaciones personalizadas
}

Anotación para Logging

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {
    String level() default "DEBUG";
    boolean includeArgs() default true;
    boolean includeResult() default false;
}

Anotación para Validación

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PowerLevelValidator.class)
public @interface PowerLevel {
    String message() default "Nivel de poder inválido";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    int min() default 1;
    int max() default 100;
}

Procesamiento de Anotaciones

Leer Anotaciones en Runtime

public void processAnnotations(Object obj) {
    Class<?> clazz = obj.getClass();

    // Leer anotaciones de clase
    if (clazz.isAnnotationPresent(HeroPower.class)) {
        HeroPower annotation = clazz.getAnnotation(HeroPower.class);
        int minLevel = annotation.minLevel();
        String description = annotation.description();
    }

    // Leer anotaciones de métodos
    for (Method method : clazz.getDeclaredMethods()) {
        if (method.isAnnotationPresent(HeroPower.class)) {
            HeroPower annotation = method.getAnnotation(HeroPower.class);
            // Procesar método
        }
    }
}

Ejemplo Completo: Servicio con Anotaciones

@ApplicationScoped
public class HeroService {

    private List<Hero> heroes = new ArrayList<>();

    @PostConstruct
    public void init() {
        // Inicializar datos después de la construcción
        heroes.add(new Hero("Superman", "Super fuerza", 95));
        heroes.add(new Hero("Batman", "Inteligencia", 85));
        logger.info("HeroService initialized with " + heroes.size() + " heroes");
    }

    @PreDestroy
    public void cleanup() {
        // Limpiar recursos antes de destruir
        heroes.clear();
        logger.info("HeroService cleaned up");
    }

    @HeroPower(minLevel = 80)
    @Loggable(level = "INFO")
    public Hero getPowerfulHero(String name) {
        return heroes.stream()
            .filter(h -> h.getName().equals(name))
            .filter(h -> h.getPowerLevel() >= 80)
            .findFirst()
            .orElse(null);
    }
}

Ciclo de Vida de Beans con Anotaciones

El ciclo de vida de un bean en Quarkus con CDI:

  1. Construcción: El bean se instancia

  2. Inyección: Las dependencias se inyectan

  3. @PostConstruct: Se ejecuta el método marcado

  4. Uso: El bean está listo para usar

  5. @PreDestroy: Se ejecuta antes de destruir (al cerrar la aplicación)

Anotaciones y CDI

Las anotaciones funcionan perfectamente con CDI:

@ApplicationScoped
@HeroPower(minLevel = 70)
public class PowerAnalysisService {

    @Inject
    HeroService heroService;

    @PostConstruct
    public void initialize() {
        // Inicialización después de la construcción e inyección
    }
}

Ejemplo Completo

Nuestro demo muestra:

  • @PostConstruct y @PreDestroy para ciclo de vida

  • @Resource para inyección de recursos

  • @Generated para código generado

  • Anotaciones personalizadas (@HeroPower, @Loggable, @PowerLevel)

  • Procesamiento de anotaciones en runtime

Ventajas en Quarkus

  1. Integración CDI: Funciona perfectamente con CDI

  2. Ciclo de Vida: Gestión automática del ciclo de vida

  3. Flexibilidad: Fácil crear anotaciones personalizadas

  4. Metadatos: Las anotaciones proporcionan metadatos útiles

Casos de Uso

Inicialización de Servicios

@PostConstruct
public void init() {
    // Cargar configuración
    // Inicializar conexiones
    // Preparar datos en memoria
}

Limpieza de Recursos

@PreDestroy
public void cleanup() {
    // Cerrar conexiones
    // Liberar recursos
    // Guardar estado
}

Anotaciones de Dominio

@HeroPower(minLevel = 90)
public class LegendaryHeroService {
    // Servicio para héroes legendarios
}

Conclusión

Las anotaciones en Quarkus proporcionan una forma poderosa de gestionar el ciclo de vida y agregar metadatos al código. Las anotaciones estándar como @PostConstruct y @PreDestroy son esenciales, mientras que las anotaciones personalizadas permiten crear APIs específicas del dominio.

Recursos

More from this blog

JoeDayz

52 posts

Community Guy | Java Champion | AWS Architect | Software Architect