Historia de la pregunta:
El patrón Dynamic Proxy apareció en Java 1.3 y permitió implementar patrones AOP, registro, seguridad, generación dinámica de código sin necesidad de escribir clases proxy manualmente. Esto se volvió muy popular en Spring, Hibernate y otros frameworks.
Problema:
A veces se requiere añadir funcionalidad a una interfaz existente o modificar el comportamiento de los métodos en tiempo de ejecución, sin cambiar el código fuente. Ejemplo: registro de cada llamada de método, verificación de acceso, perfilado. El problema principal es la imposibilidad de hacerlo "manualmente" para todas las clases, especialmente si hay muchas clases o se generan dinámicamente.
Solución:
Java proporciona una API estándar en el paquete java.lang.reflect para crear objetos proxy "al vuelo" para cualquier interfaz usando Proxy.newProxyInstance. Se implementa el objeto InvocationHandler, que recibe cada llamada de método y ejecuta su lógica.
Ejemplo de código:
import java.lang.reflect.*; interface Service { void serve(); } class ServiceImpl implements Service { public void serve() { System.out.println("Sirviendo..."); } } class LoggingHandler implements InvocationHandler { private final Object target; public LoggingHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Llamando " + method.getName()); return method.invoke(target, args); } } Service service = (Service) Proxy.newProxyInstance( Service.class.getClassLoader(), new Class[]{Service.class}, new LoggingHandler(new ServiceImpl())); service.serve();
Características clave:
¿Se puede "envolver" una clase normal que no implementa interfaces usando el proxy dinámico estándar?
No. El proxy dinámico solo funciona con interfaces. Para clases se necesita manipulación de bytecode (por ejemplo, CGLIB).
¿Qué sucederá si la interfaz contiene métodos con tipos de retorno incompatibles con el valor de retorno del InvocationHandler?
Se lanzará un ClassCastException, por lo que el valor de retorno debe ser estrictamente compatible con la definición de la interfaz.
¿Se puede usar un proxy dinámico para métodos final?
No. El proxy solo funciona a nivel de interfaces, y ahí no hay métodos final. Los métodos final no se pueden sobrescribir en absoluto.
Caso negativo
El desarrollador intentó implementar registro de auditoría a través de Proxy en clases sin interfaz.
Pros:
Contras:
Caso positivo
Se definió un contrato a través de una interfaz, ya se hizo la envoltura proxy para ello.
Pros:
Contras: