2012-05-19 26 views
94

In caso di Proxy Design Pattern, Qual è la differenza tra JDK's Dynamic Proxy e API di generazione di codice dinamico di terze parti come CGLib?Qual è la differenza tra il proxy dinamico JDK e CGLib?

Qual è la differenza tra l'utilizzo di entrambi gli approcci e quando si preferisce uno rispetto all'altro?

+3

Ottieni il codice qui: . In cglib puoi creare sia proxy di classe che proxy di interfaccia. Spring utilizza CGlib per impostazione predefinita mentre AspectJ utilizza il proxy Java. Leggi anche questo: http://jnb.ociweb.com/jnb/jnbNov2005.html;) –

risposta

127

JDK Il proxy dinamico può solo proxy per interfaccia (quindi la classe di destinazione deve implementare un'interfaccia, che viene quindi implementata anche dalla classe proxy).

CGLIB (e javassist) può creare un proxy per sottoclasse. In questo scenario il proxy diventa una sottoclasse della classe di destinazione. Non c'è bisogno di interfacce.

proxy

Così Java dinamico può delega: public class Foo implements iFoo dove CGLIB può delega: public class Foo

EDIT:

Devo dire che a causa javassist e CGLIB utilizzare proxy sottoclassi, che questa è la ragione per cui non è possibile dichiarare finale metodi o rendere la classe finale quando si usano framework che si basano su questo. Ciò impedirebbe a queste librerie di consentire di sottoclasse la classe e sovrascrivere i metodi.

+0

tHANKS .. !! ma sarebbe utile se potessi darmi un codice di esempio (o Link) per illustrare il proprio uso rispetto ad un altro in alcuni casi .. !!! – KDjava

+3

L'elenco dei codici su http://www.edc4it.com/2011/11/03/jpa-transactional-proxy-for-javase/ crea un proxy usando javassist. Qui: http://www.edc4it.com/2011/03/01/using-run-time-bytecode-instrumentation-bci/ è un esempio che utilizza CGLib. Un esempio che utilizza i proxy Java dinamici può essere trovato http://docs.oracle.com/javase/1.3/docs/guide/reflection/proxy.html –

+0

codice CGLIB- http://www.edc4it.com/2011/03/01/using-run-time-bytecode-instrumentation-bci/è stato davvero interessante e utile anche ... Grazie mille !! – KDjava

35

Differenze nella funzionalità

  • I proxy JDK permettono di realizzare qualsiasi insieme di interfacce mentre sottoclassi java.lang.reflect.Proxy. Qualsiasi metodo di interfaccia, più Object::hashCode, Object::equals e Object::toString viene quindi inoltrato a InvocationHandler.

  • cglib consente di implementare qualsiasi insieme di interfacce sottoclasse qualsiasi classe non definitiva. Inoltre, i metodi possono essere sovrascritti facoltativamente, cioè non tutti i metodi non astratti devono essere intercettati. Inoltre, ci sono diversi modi per implementare un metodo. Offre anche una classe (in un pacchetto diverso), ma consente anche di chiamare metodi super utilizzando interceptor più avanzati come ad esempio uno MethodInterceptor. Inoltre, cglib può migliorare le prestazioni con intercettazioni specializzate come FixedValue. Una volta ho scritto a summary of different interceptors for cglib.

differenze di prestazioni

JDK proxy sono implementate piuttosto ingenuamente con un solo dispatcher intercettazione, il InvocationHandler. Ciò richiede l'invio di un metodo virtuale a un'implementazione che non può sempre essere sottolineata. Cglib consente di creare codice byte specializzato che a volte può migliorare le prestazioni. Ecco alcuni confronti di attuazione un'interfaccia con metodi 18 stub:

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

Il tempo è notato in nanosecondi con deviazione standard in parentesi. Puoi trovare maggiori dettagli sul benchmark in Byte Buddy's tutorial, dove Byte Buddy è un'alternativa più moderna a cglib. Inoltre, si noti che cglib non è più in fase di sviluppo attivo.

+1

Perché la documentazione di primavera favorisce il proxy di JDK rispetto a cglib, dati i vantaggi in termini di prestazioni di quest'ultimo? http://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-proxying – P4ndaman

+1

Cglib è una dependence esterna e attualmente non supportata. Affidarsi a software di terze parti è sempre una scommessa, quindi è meglio affidarsi al minor numero possibile di persone. –

+0

* Questa * dovrebbe essere la risposta accettata! –

12

delega dinamico: implementazioni dinamiche delle interfacce nei runtime utilizzando JDK API Reflection.

Esempio: Spring usa proxy dinamici per operazioni come segue:

enter image description here

Il proxy generata viene in cima fagiolo. Aggiunge un comportamento transnazionale al bean. Qui il proxy genera dinamicamente in fase di runtime utilizzando l'API JDK Reflection.

Quando un'applicazione viene arrestata, il proxy verrà distrutto e avremo solo l'interfaccia e il bean sul file system.


Nell'esempio precedente abbiamo un'interfaccia. Ma nella maggior parte delle implementazioni di interfaccia non è la migliore. Quindi fagioli non implementa un'interfaccia, in questo caso abbiamo utilizza l'ereditarietà:

enter image description here

Al fine di generare tali deleghe, Primavera utilizza una libreria di terze parti chiamato CGLIB.

CGLIB (C odalità G eneration Lib Rary) è costruito in cima ASM, questo è usato principalmente il proxy generare estendentesi fagioli e aggiunge comportamento fagiolo nei metodi proxy.

Examples for JDK Dynamic proxy and CGLib

Spring ref

0

From Spring documentation:

Spring AOP utilizza sia proxy dinamici JDK o CGLIB per creare il proxy per un oggetto bersaglio. (I proxy dinamici JDK sono preferiti ogni volta che si ha una scelta).

Se l'oggetto di destinazione da proxy implementa almeno un'interfaccia, verrà utilizzato un proxy dinamico JDK. Tutte le interfacce implementate dal tipo di destinazione verranno proxy. Se l'oggetto di destinazione non implementa alcuna interfaccia, verrà creato un proxy CGLIB.

Se si desidera forzare l'utilizzo del proxy CGLIB (ad esempio, per eseguire il proxy di ogni metodo definito per l'oggetto di destinazione, non solo quelli implementati dalle sue interfacce) è possibile farlo. Tuttavia, ci sono alcuni aspetti da considerare:

i metodi finali non possono essere consigliati, in quanto non possono essere sostituiti.

Avrete bisogno dei binari CGLIB 2 sul classpath, mentre i proxy dinamici sono disponibili con JDK. Spring ti avviserà automaticamente quando ha bisogno di CGLIB e le classi della libreria CGLIB non vengono trovate sul classpath.

Il costruttore dell'oggetto proxy verrà chiamato due volte. Questa è una conseguenza naturale del modello di proxy CGLIB in base al quale viene generata una sottoclasse per ciascun oggetto proxy. Per ogni istanza proxy, vengono creati due oggetti: l'oggetto proxy reale e un'istanza della sottoclasse che implementa il consiglio. Questo comportamento non è mostrato quando si utilizzano i proxy JDK. Di solito, chiamare due volte il costruttore del tipo proxy, non è un problema, dato che di solito ci sono solo assegnazioni in corso e nessuna logica reale è implementata nel costruttore.