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 paquetecom.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. 😉
GO TO FULL VERSION