Repository navigation
Expand file tree
/
Copy pathExpAOP.java
More file actions
124 lines (101 loc) · 4.72 KB
/
Copy pathExpAOP.java
File metadata and controls
124 lines (101 loc) · 4.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// AOP - Programación Orientada a Aspectos simulada con JDK Dynamic Proxy
// En Spring: @Aspect + @Component sobre una clase con métodos @Before / @Around / etc.
// Aquí: InvocationHandler implementa los 4 advice types sin ninguna dependencia de Spring/AspectJ.
public class ExpAOP {
// --- Interfaz de negocio (join point target) ---
interface PagosService {
double procesar(String concepto, double importe);
void rechazar(String motivo);
}
// Implementación real — equivalente al @Service interceptado en Spring AOP
static class PagosServiceImpl implements PagosService {
@Override
public double procesar(String concepto, double importe) {
System.out.println(" [SERVICE] Procesando pago: " + concepto + " - " + importe + "€");
return importe * 1.21; // IVA incluido
}
@Override
public void rechazar(String motivo) {
System.out.println(" [SERVICE] Pago rechazado: " + motivo);
throw new IllegalStateException("Pago rechazado: " + motivo);
}
}
// --- Aspect simulado como InvocationHandler ---
// En Spring: @Aspect @Component public class PagosAspect { ... }
static class PagosAspect implements InvocationHandler {
private final Object target;
PagosAspect(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// @Before — se ejecuta ANTES del método
// En Spring: @Before("execution(* PagosService.*(..))")
before(method);
long inicio = System.currentTimeMillis();
Object resultado = null;
Throwable excepcion = null;
// @Around — rodea la ejecución completa; pjp.proceed() = method.invoke(target, args)
// En Spring: @Around("execution(* PagosService.*(..))")
try {
resultado = method.invoke(target, args);
// @AfterReturning — solo si el método retornó sin excepción
// En Spring: @AfterReturning(pointcut = "...", returning = "resultado")
afterReturning(method, resultado);
} catch (Throwable t) {
excepcion = t.getCause() != null ? t.getCause() : t;
// @AfterThrowing — solo si el método lanzó excepción
// En Spring: @AfterThrowing(pointcut = "...", throwing = "ex")
afterThrowing(method, excepcion);
throw excepcion;
} finally {
// Parte "after" del @Around — siempre se ejecuta
long tiempo = System.currentTimeMillis() - inicio;
aroundMetrics(method, tiempo);
}
return resultado;
}
// @Before advice
private void before(Method method) {
System.out.println("[BEFORE] Ejecutando: " + method.getName() + "()");
}
// @AfterReturning advice
private void afterReturning(Method method, Object resultado) {
System.out.println("[AFTER_RETURNING] " + method.getName()
+ " completado. Resultado: " + resultado);
}
// @AfterThrowing advice
private void afterThrowing(Method method, Throwable ex) {
System.out.println("[AFTER_THROWING] " + method.getName()
+ " lanzó excepción: " + ex.getMessage());
}
// @Around metrics
private void aroundMetrics(Method method, long ms) {
System.out.println("[AROUND/METRICS] " + method.getName() + ": " + ms + " ms");
}
}
// --- Fábrica de proxies (equivale a Spring creando CGLIB/JDK proxies) ---
@SuppressWarnings("unchecked")
static <T> T crearProxy(T target, Class<T> interfaz) {
return (T) Proxy.newProxyInstance(
interfaz.getClassLoader(),
new Class<?>[]{ interfaz },
new PagosAspect(target)
);
}
public static void main(String[] args) {
PagosService servicio = crearProxy(new PagosServiceImpl(), PagosService.class);
System.out.println("=== Caso 1: método que retorna valor ===");
double total = servicio.procesar("Suscripción mensual", 9.99);
System.out.println("Total con IVA: " + total + "€");
System.out.println("\n=== Caso 2: método que lanza excepción ===");
try {
servicio.rechazar("Saldo insuficiente");
} catch (IllegalStateException e) {
System.out.println("[MAIN] Excepción manejada: " + e.getMessage());
}
}
}