2012-05-19 14 views
94

En el caso de Proxy Design Pattern, ¿cuál es la diferencia entre JDK's Dynamic Proxy y API de generación de código dinámico de terceros como CGLib?¿Cuál es la diferencia entre el proxy dinámico JDK y CGLib?

¿Cuál es la diferencia entre utilizar ambos enfoques y cuándo se debe preferir uno sobre otro?

+3

Obtén el código aquí: . En cglib puede crear proxy de clase y proxy de interfaz. Spring usa CGlib por defecto mientras AspectJ usa Java proxy. Lea esto también: http://jnb.ociweb.com/jnb/jnbNov2005.html;) –

Respuesta

127

JDK El proxy dinámico solo puede realizar un proxy por interfaz (por lo que su clase objetivo necesita implementar una interfaz, que luego también implementa la clase proxy).

CGLIB (y javassist) pueden crear un proxy mediante subclases. En este escenario, el proxy se convierte en una subclase de la clase objetivo. Sin necesidad de interfaces

proxies

Así Java dinámicos Puede actuar como apoderado: public class Foo implements iFoo donde CGLIB Puede actuar como apoderado: public class Foo

EDIT:

Debo mencionar que debido a javassist y CGLIB utilizan proxy subclases, que esta es la razón por la que no se puede declarar definitiva métodos o hacer que la clase sea definitiva cuando se utilizan marcos que dependen de esto. Eso evitaría que estas bibliotecas dejaran subclase a su clase y anularan sus métodos.

+0

tHANKS .. !! pero sería útil si pudiera darme un código de ejemplo (o un enlace) para ilustrar el uso de uno sobre otro en algún caso ... !!! – KDjava

+3

El listado del código en http://www.edc4it.com/2011/11/03/jpa-transactional-proxy-for-javase/ crea un proxy usando javassist. Aquí: http://www.edc4it.com/2011/03/01/using-run-time-bytecode-instrumentation-bci/ es un ejemplo usando CGLib. Puede encontrar un ejemplo con proxys Java Dynamic http://docs.oracle.com/javase/1.3/docs/guide/reflection/proxy.html –

+0

el código CGLIB- http://www.edc4it.com/2011/03/01/using-run-time-bytecode-instrumentation-bci/fue realmente interesante y útil también ... ¡Muchas gracias! – KDjava

35

Diferencias de las funciones

  • Los proxies JDK permiten implementar cualquier conjunto de interfaces, mientras que la subclasificación java.lang.reflect.Proxy. Cualquier método de interfaz, más Object::hashCode, Object::equals y Object::toString se reenvía a InvocationHandler.

  • cglib le permite implementar cualquier conjunto de interfaces mientras subclasifica cualquier clase no final. Además, los métodos pueden anularse opcionalmente, es decir, no es necesario interceptar todos los métodos no abstractos. Además, hay diferentes formas de implementar un método. También ofrece una clase InvocationHandler (en un paquete diferente), pero también permite llamar a los súper métodos mediante el uso de interceptores más avanzados como, por ejemplo, un MethodInterceptor. Además, cglib puede mejorar el rendimiento mediante intercepciones especializadas como FixedValue. Una vez escribí a summary of different interceptors for 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 puede estar en línea. Cglib permite crear código de bytes especializado, lo que a veces puede mejorar el rendimiento. Aquí están algunas comparaciones para implementar una interfaz con métodos stub 18:

  cglib     JDK proxy 
creation 804.000  (1.899)  973.650  (1.624) 
invocation 0.002  (0.000)  0.005  (0.000) 

Se anota el tiempo en nanosegundos con una desviación estándar en los apoyos. Puede encontrar más detalles sobre el índice de referencia en Byte Buddy's tutorial, donde Byte Buddy es una alternativa más moderna a cglib. Además, tenga en cuenta que cglib ya no se encuentra en desarrollo activo.

+1

¿Por qué la documentación de primavera favorece el proxying JDK sobre cglib dados los beneficios de rendimiento de este último? http://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-proxying – P4ndaman

+1

Cglib es una dependencia externa y actualmente no es compatible. Confiar en un software de terceros siempre es una apuesta, por lo que es mejor cuando la menor cantidad posible de personas confíe en él. –

+0

* ¡Esta * debería ser la respuesta aceptada! –

12

proxy dinámico: implementaciones dinámicas de las interfaces en tiempo de ejecución usando JDK Reflexión API.

Ejemplo: primavera utiliza proxies dinámicos para las transacciones de la siguiente manera:

enter image description here

El proxy generado entra en la parte superior de frijol. Agrega comportamiento transnacional al frijol. Aquí el proxy genera dinámicamente en tiempo de ejecución utilizando JDK Reflection API.

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 la interfaz. Pero en la mayoría de la implementación de la interfaz no es lo mejor. Así frijol no implementa una interfaz, en ese caso se utiliza la herencia:

enter image description here

Con el fin de generar tales proxies, Primavera utiliza un biblioteca de terceros llama CGLIB.

CGLIB (C oda G eneration Lib Rary) se construye en la parte superior de ASM, este se utiliza principalmente el proxy generar extiende bean y añade comportamiento de frijol en los métodos de proxy.

Examples for JDK Dynamic proxy and CGLib

Spring ref

0

From Spring documentation:

primavera AOP utiliza cualquiera de proxies dinámicos JDK o CGLIB para crear el proxy para un objeto de destino dado. (Los proxies dinámicos JDK son preferidos siempre que tenga una opción).

Si el objeto de destino a ser procesado implementa al menos una interfaz, entonces se usará un proxy dinámico JDK. Todas las interfaces implementadas por el tipo de objetivo serán procesadas. Si el objeto objetivo no implementa ninguna interfaz, se creará un proxy CGLIB.

Si desea forzar el uso del proxying CGLIB (por ejemplo, para proxy de cada método definido para el objeto de destino, no solo aquellos implementados por sus interfaces) puede hacerlo. Sin embargo, hay algunos problemas que se deben tener en cuenta:

No se pueden recomendar los métodos finales, ya que no se pueden anular.

Necesitará los binarios de CGLIB 2 en su classpath, mientras que los proxies dinámicos están disponibles con el JDK. Spring le advertirá automáticamente cuando necesite CGLIB y las clases de biblioteca CGLIB no se encontrarán en la ruta de clase.

El constructor de su objeto con proxy se llamará dos veces. Esta es una consecuencia natural del modelo de proxy CGLIB mediante el cual se genera una subclase para cada objeto con proxy. Para cada instancia de proxy, se crean dos objetos: el objeto proxy real y una instancia de la subclase que implementa el consejo. Este comportamiento no se muestra cuando se utilizan proxys JDK. Por lo general, llamar al constructor del tipo de proxy dos veces no es un problema, ya que normalmente solo se llevan a cabo asignaciones y no se implementa una lógica real en el constructor.

Cuestiones relacionadas