CodeGym /Cursos /Módulo 5. Spring /Práctica: configurar un aspecto sencillo para logging

Práctica: configurar un aspecto sencillo para logging

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

Vamos a crear un ejemplo práctico donde configuraremos un aspecto para logging.

1. Logging: ¿qué y para qué?

El logging es el proceso de registrar información sobre la ejecución de la aplicación. Te ayuda a ver qué pasa "bajo el capó" y se convierte en un artefacto clave para depuración y análisis en entornos de producción.

Por ejemplo, si tienes un método que procesa un pedido en una tienda online, es útil saber:

  • Cuándo se llamó a ese método.
  • Qué datos se pasaron como parámetros.
  • Qué ocurrió dentro del método: si fue éxito o hubo un error.

Con AOP podemos inyectar logging sin tocar la lógica de negocio de los métodos. O sea, tu código se mantiene limpio y la funcionalidad se añade a nivel de aspecto.


2. Configurar el proyecto

Paso 1: Añade las dependencias

Crea un proyecto Spring Boot (si aún no lo hiciste) y asegúrate de que spring-boot-starter-aop esté en tu pom.xml (o build.gradle):


<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Paso 2: Habilita el soporte para AOP

Spring Boot activa AOP automáticamente si añadiste la dependencia. No necesitas configuración extra. Pero si usas Spring Framework sin Boot, asegúrate de tener el componente @EnableAspectJAutoProxy en la configuración.


3. Crear un aspecto para logging

Empezamos con un aspecto simple para loggear métodos.

Paso 1: Crea la clase del aspecto

Crea una nueva clase LoggingAspect en tu proyecto:


import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.demo.service.*.*(..))") // Indica dónde aplicar el aspecto
    public void logBeforeMethodExecution() {
        System.out.println("A method in the service layer is about to be called.");
    }
}

Análisis del código:

  • @Aspect — indica que esta clase es un aspecto.
  • @Component — registra el aspecto como un Spring Bean.
  • @Before — determina que la acción indicada (logBeforeMethodExecution) debe ejecutarse antes de la llamada al método.
  • "execution(* com.example.demo.service.*.*(..))" — es la expresión Pointcut. Selecciona todos los métodos del paquete com.example.demo.service.

Paso 2: Crea un servicio para probar

Añadamos un servicio simple para verificar nuestro logging. Para eso, en el paquete service crea la clase OrderService:


package com.example.demo.service;

import org.springframework.stereotype.Service;

@Service
public class OrderService {

    public void processOrder(String orderId) {
        System.out.println("Processing order with ID: " + orderId);
    }
}

Paso 3: Crea el controlador

Para comprobar el funcionamiento del aspecto, creemos un controlador. Añade la nueva clase OrderController:


package com.example.demo.controller;

import com.example.demo.service.OrderService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {

    private final OrderService orderService;

    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }

    @GetMapping("/process-order")
    public String processOrder(@RequestParam String orderId) {
        orderService.processOrder(orderId);
        return "Order processed!";
    }
}

4. ¡Probamos!

Arranca la aplicación y abre el navegador. Escribe la URL, por ejemplo:


http://localhost:8080/process-order?orderId=123

Deberías ver el resultado en la consola:


A method in the service layer is about to be called.
Processing order with ID: 123

¡Listo! Has añadido logging al método del servicio sin modificar su código.


5. Mejoramos el aspecto: loggear los argumentos

Vamos a añadir la posibilidad de loggear los parámetros de la llamada al método. Para eso usa la API JoinPoint. Actualiza tu aspecto así:


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.demo.service.*.*(..))")
    public void logBeforeMethodExecution(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] methodArguments = joinPoint.getArgs();

        System.out.println("Method " + methodName + " is called with arguments: ");

        for (Object arg : methodArguments) {
            System.out.println("    " + arg);
        }
    }
}

Ahora, al invocar el método verás en la consola:


Method processOrder is called with arguments:
    123
Processing order with ID: 123

Esto hace que el logging sea mucho más informativo.


6. Añadimos @Around para medir el tiempo de ejecución

El siguiente paso: medir el tiempo de ejecución de los métodos. Actualicemos el aspecto usando @Around:


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class PerformanceLoggingAspect {

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

        Object result = joinPoint.proceed(); // Ejecutar el método

        long endTime = System.currentTimeMillis();
        System.out.println("Execution time of " + joinPoint.getSignature().getName() +
                ": " + (endTime - startTime) + "ms");

        return result;
    }
}

Ahora, cuando llames al método también obtendrás información sobre su tiempo de ejecución:


Processing order with ID: 123
Execution time of processOrder: 5ms

7. Feedback: errores típicos

Uno de los errores más comunes al usar AOP es definir mal el Pointcut. Por ejemplo, si pones un Pointcut demasiado "amplio", tu aspecto puede empezar a dispararse en métodos inesperados, como toString(). Para evitarlo, procura especificar bien paquetes y clases.


8. ¿Y ahora qué?

Añadir niveles de logging, gestionar dinámicamente aspectos vía archivos de configuración, crear aspectos para manejar excepciones... Bienvenido al mundo de posibilidades de Spring AOP.

Ahora tienes una herramienta que te hace la vida más fácil. Úsala con cabeza y con cuidado, como una varita mágica. 😉

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