En el caso del patrón de diseño de proxy , ¿cuál es la diferencia entre el proxy dinámico de JDK y las API de generación de código dinámico de terceros como CGLib ?
¿Cuál es la diferencia entre usar ambos enfoques y cuándo debería uno preferir uno sobre otro?
java
reflection
cglib
dynamic-proxy
KDjava
fuente
fuente
Respuestas:
El proxy dinámico JDK solo puede usar proxy por interfaz (por lo que su clase objetivo necesita implementar una interfaz, que luego también implementa la clase proxy).
CGLIB (y javassist) puede crear un proxy subclasificando. En este escenario, el proxy se convierte en una subclase de la clase de destino. No hay necesidad de interfaces.
Entonces, los proxies dinámicos de Java pueden proxy:
public class Foo implements iFoo
donde CGLIB puede proxy:public class Foo
EDITAR:
Debo mencionar que debido a que javassist y CGLIB usan proxy mediante subclases, esta es la razón por la que no puede declarar métodos finales o hacer que la clase sea final cuando se usan marcos que dependen de esto. Eso evitaría que estas bibliotecas permitan subclasificar su clase y anular sus métodos.
fuente
Diferencias en funcionalidad
Los proxys JDK permiten implementar cualquier conjunto de interfaces durante la subclase
Object
. Cualquier método de interfaz, másObject::hashCode
,Object::equals
yObject::toString
luego se reenvía a unInvocationHandler
. Además,java.lang.reflect.Proxy
se implementa la interfaz de biblioteca estándar .cglib le permite implementar cualquier conjunto de interfaces mientras subclasifica cualquier clase no final. Además, los métodos se pueden anular opcionalmente, es decir, no todos los métodos no abstractos deben ser interceptados. Además, hay diferentes formas de implementar un método. También ofrece una
InvocationHandler
clase (en un paquete diferente), pero también permite llamar a métodos súper utilizando interceptores más avanzados como, por ejemplo, aMethodInterceptor
. Además, cglib puede mejorar el rendimiento mediante intercepciones especializadas comoFixedValue
. Una vez escribí un resumen de diferentes interceptores para cglib .Diferencias de rendimiento
Proxies JDK se implementan ingenuamente con sólo un despachador de intercepción, la
InvocationHandler
. Esto requiere un envío de método virtual a una implementación que no siempre se puede incorporar. Cglib permite crear códigos de bytes especializados que a veces pueden mejorar el rendimiento. Aquí hay algunas comparaciones para implementar una interfaz con 18 métodos stub:El tiempo se observa en nanosegundos con desviación estándar entre llaves. Puede encontrar más detalles sobre el punto de referencia en el tutorial de Byte Buddy, donde Byte Buddy es una alternativa más moderna a cglib. Además, tenga en cuenta que cglib ya no está en desarrollo activo.
fuente
Proxy dinámico: implementaciones dinámicas de interfaces en tiempo de ejecución utilizando JDK Reflection API .
Ejemplo: Spring usa proxys dinámicos para transacciones de la siguiente manera:
El proxy generado viene encima del bean. Agrega comportamiento transnacional al frijol. Aquí, el proxy se genera dinámicamente en tiempo de ejecución utilizando la API JDK Reflection.
Cuando se detiene una aplicación, el proxy se destruirá y solo tendremos interfaz y bean en el sistema de archivos.
En el ejemplo anterior tenemos interfaz. Pero en la mayoría de la implementación de la interfaz no es la mejor. Entonces bean no implementa una interfaz, en ese caso usamos herencia:
Para generar tales proxies, Spring usa una biblioteca de terceros llamada CGLib .
CGLib ( C ode G eneration Lib rary ) está construido sobre ASM , esto se usa principalmente para generar proxy extendiendo bean y agrega comportamiento de bean en los métodos proxy.
Ejemplos de proxy dinámico JDK y CGLib
Ref primavera
fuente
De la documentación de Spring :
fuente