Spring AOP se basa en el Patrón Proxy y la generación dinámica de clases para aplicar aspectos sin modificar el código fuente original.
Spring AOP crea proxies para interceptar llamadas a métodos y aplicar lógica adicional. Dependiendo de la estructura de la clase objetivo, Spring elige entre dos enfoques:
JDK Dynamic Proxies: Si la clase implementa una interfaz, Spring usa java.lang.reflect.Proxy para generar un proxy en tiempo de ejecución.
CGLIB (Code Generation Library): Si la clase no implementa interfaces, se genera una subclase dinámica con CGLIB.
Veamos un ejemplo de un proxy con JDK:
import java.lang.reflect.*;
interface Servicio {
void ejecutar();
}
class ServicioImpl implements Servicio {
public void ejecutar() {
System.out.println("Ejecutando servicio...");
}
}
class ProxyHandler implements InvocationHandler {
private final Object target;
public ProxyHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("[AOP] Antes de ejecutar");
Object result = method.invoke(target, args);
System.out.println("[AOP] Después de ejecutar");
return result;
}
}
public class Main {
public static void main(String[] args) {
Servicio servicio = (Servicio) Proxy.newProxyInstance(
Servicio.class.getClassLoader(),
new Class[]{Servicio.class},
new ProxyHandler(new ServicioImpl()));
servicio.ejecutar();
}
}
Si la clase no implementa interfaces, Spring usa CGLIB para generar una subclase dinámica.
import net.sf.cglib.proxy.*;
class Servicio {
public void ejecutar() {
System.out.println("Ejecutando servicio...");
}
}
class Interceptor implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("[AOP] Antes de ejecutar");
Object result = proxy.invokeSuper(obj, args);
System.out.println("[AOP] Después de ejecutar");
return result;
}
}
public class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Servicio.class);
enhancer.setCallback(new Interceptor());
Servicio proxy = (Servicio) enhancer.create();
proxy.ejecutar();
}
}
Spring AOP aplica aspectos mediante proxies dinámicos. Si la clase tiene una interfaz, usa JDK Dynamic Proxies; si no, usa CGLIB para generar una subclase dinámica. Esto permite agregar lógica sin modificar el código fuente ni el bytecode.