CodeGym /Cursos /Módulo 5. Spring /Introducción a AOP (programación orientada a aspectos)

Introducción a AOP (programación orientada a aspectos)

Módulo 5. Spring
Nivel 3 , Lección 0
Disponible

1. Conceptos básicos de AOP

Para no perderte entre abreviaturas, aclaremos las definiciones.

programación orientada a aspectos (AOP) — es una paradigma que permite extraer e encapsular las llamadas "cross-cutting concerns" (preocupaciones transversales).

¿Qué son las "preocupaciones transversales"?

Imagina que tienes una aplicación con muchos módulos. En cada módulo necesitas, por ejemplo, registrar acciones, gestionar transacciones o validar parámetros. La lógica de estas tareas no pertenece directamente a la funcionalidad de negocio del módulo — son "tareas transversales". Lo más sensato es centralizar ese código en un solo sitio para no duplicarlo en todos los módulos, evitando que la arquitectura parezca un patchwork de piezas repetidas.

Ventajas de AOP:

  1. Modularidad — puedes aislar la lógica de esas tareas y aplicarla donde haga falta.
  2. Código más limpio — menos código repetido en la lógica de negocio.
  3. Facilidad para modificar — cambios en la "tarea transversal" se aplican automáticamente en todos los puntos donde se usa.

AOP en proyectos reales

¿La teoría ya te ha aburrido? Vale, vamos a ver escenarios reales donde AOP se muestra con todo su potencial:

  • Registro: salida automática del tiempo de ejecución de los métodos, parámetros de la llamada y resultado.
  • Transacciones: gestión de transacciones en bases de datos.
  • Seguridad: comprobación de permisos de los usuarios.
  • Caching: puedes cachear automáticamente los resultados de un método.
  • Manejo de errores: un handler centralizado para excepciones.

AOP simplifica tu código y te permite centrarte en la lógica de negocio en lugar de en la rutina.


2. Conceptos principales de AOP: Aspecto, Pointcut, Advice

El conocimiento de AOP estaría incompleto sin estudiar tres conceptos clave. Ahora los vemos con ejemplos:

Aspecto (Aspect)

Aspecto — es un módulo que encapsula la lógica de tareas transversales. Por ejemplo, si quieres registrar la ejecución de métodos, creas un aspecto para logging.

Piensa en un aspecto como un observador independiente de tu código. Y ese observador interviene solo cuando hace falta.

Ejemplo:


@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.*.*(..))") // Definimos dónde se activa el aspecto
    public void logMethodCall() {
        System.out.println("¡Método invocado!");
    }
}

Pointcut (Pointcut)

Pointcut — es una expresión que indica exactamente dónde (en qué puntos) el aspecto debe "colarse". El pointcut "resalta" los join points — los puntos en el código donde se puede añadir comportamiento vía aspectos.

Puedes imaginar la sintaxis de los pointcuts como un lenguaje para filtrar métodos:

  • execution(* com.example.service.*.*(..)) — invocar el aspecto para todos los métodos en el paquete service.
  • execution(public * *(..)) — aplicar el aspecto a todos los métodos públicos.

Advice (Advice)

Advice — es el código que define "qué" y "cuándo" ejecutar en el join point. Hay cinco tipos de advices:

  • Before — la acción se ejecuta antes del método.
  • After — la acción se ejecuta después del método.
  • AfterReturning — se ejecuta después de que el método termine con éxito.
  • AfterThrowing — se ejecuta si el método lanza una excepción.
  • Around — controlas la ejecución del método (¡incluso puedes cancelarla!).

Ejemplo de uso de advices:


@Aspect
@Component
public class DetailedLoggingAspect {

    @Before("execution(* com.example.service.*.*(..))")
    public void beforeMethodCall() {
        System.out.println("Antes de llamar al método");
    }

    @AfterReturning("execution(* com.example.service.*.*(..))")
    public void afterReturningFromMethod() {
        System.out.println("Método finalizado con éxito");
    }

    @AfterThrowing("execution(* com.example.service.*.*(..))")
    public void afterExceptionThrown() {
        System.out.println("¡El método lanzó una excepción!");
    }
}

Ya tenemos claro cómo funcionan los advices. ¡Vamos a la práctica!


3. Cómo AOP resuelve problemas en tu aplicación

Registro

Veamos una situación típica: tienes montones de métodos y quieres saber cuándo se ejecutan y con qué parámetros.


@Aspect
@Component
public class LoggingAspect {

    @Around("execution(* com.example.service.*.*(..))")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();

        Object result = joinPoint.proceed();  // Llamada al método

        long executionTime = System.currentTimeMillis() - start;
        System.out.println(joinPoint.getSignature() + " ejecutado en " + executionTime + " ms");

        return result;
    }
}

Gestión de transacciones

Con un aspecto es más fácil configurar el comportamiento transaccional — la lógica queda separada del código principal:


@Component
@Aspect
public class TransactionAspect {

    @Around("execution(* com.example.service.*.*(..))")
    public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Transacción iniciada");
        Object result;
        try {
            result = joinPoint.proceed(); // Llamada al método
            System.out.println("Transacción completada");
        } catch (Exception e) {
            System.out.println("Reversión de la transacción por error");
            throw e;
        }
        return result;
    }
}

Seguridad

Con AOP puedes añadir fácilmente comprobaciones de permisos en los métodos:


@Aspect
@Component
public class SecurityAspect {

    @Before("execution(* com.example.service.*.*(..))")
    public void checkUserAccess() {
        // Pseudocódigo
        if (!userHasAccess()) {
            throw new SecurityException("¡Acceso denegado!");
        }
    }
}

4. Integración de AOP en una aplicación Spring

Para trabajar con AOP en Spring necesitas añadir el módulo spring-boot-starter-aop. Si usas Spring Boot, normalmente se configura automáticamente.

Ejemplo de configuración

  1. Asegúrate de que la dependencia spring-boot-starter-aop está añadida en pom.xml:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. Anota los aspectos con @Aspect, y tu clase de la tarea transversal con @Component.

5. ¿Para qué sirve esto en proyectos reales?

AOP te libra de la copia y pega infinita de código de utilidad por todo el sistema. Imagina que tienes decenas de microservicios y quieres cambiar la lógica de logging. Sin AOP tendrías que entrar en el código de cada servicio y modificarlo a mano — tiempo y riesgo de errores. AOP te permite mover esa funcionalidad a un único sitio y gestionarla de forma centralizada.

En entrevistas, conocer AOP demuestra que entiendes enfoques arquitectónicos. Además, ser capaz de explicar cómo los aspectos facilitan el mantenimiento del código te hace un candidato más fuerte.

¿Seguimos? En las siguientes lecciones nos esperan los entresijos de Pointcut y la personalización de aspectos. ¡Nos vemos en el siguiente método! 😄

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION