Qual è la differenza tra JDK Dynamic Proxy e Cglib?
-
11-12-2019 - |
Domanda
In caso di modello di progettazione proxy , qual è la differenza tra Dynamic Proxy JDK e terze parti Dynamic Generation API s come cglib ?
Qual è la differenza tra l'utilizzo di entrambi gli approcci che quando si preferisce uno su un altro?
Soluzione
JDK Dynamic Proxy 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 dalla sottoclassamento.In questo scenario il proxy diventa una sottoclasse della classe target.Non c'è bisogno di interfacce.
Allora Java Dynamic Proxys può proxy: public class Foo implements iFoo
dove cglib può proxy: public class Foo
Modifica:
Dovrei menzionare che poiché Javassist e Cglib utilizzano proxy mediante la sottoclassamento, che questo è il motivo per cui non è possibile dichiarare metodi finali o rendere la finale della classe quando si utilizzano frameworks che si basano su questo.Ciò impedirebbe a queste biblioteche di consentendo di sottoclasse la tua classe e sovrascrivere i tuoi metodi.
Altri suggerimenti
Differenze in funzionalità
- .
-
I proxy JDK consentono di implementare qualsiasi set di interfacce durante la sottoclassificazione
Object
. Qualsiasi metodo di interfaccia, plusObject::hashCode
,Object::equals
eObject::toString
viene quindi inoltrato a unInvocationHandler
. Inoltre, viene implementata l'interfaccia della libreria standardjava.lang.reflect.Proxy
. -
cglib consente di implementare qualsiasi set di interfacce durante la sottoclassamento della classe non finale. Inoltre, i metodi possono essere sovrascritti opzionalmente, cioè non tutti i metodi non astratti devono essere intercettati. Inoltre, ci sono diversi modi di implementare un metodo. Offre anche una classe
InvocationHandler
(in un pacchetto diverso), ma consente inoltre di chiamare i metodi super utilizzando intercettori più avanzati come ad esempio unMethodInterceptor
. Inoltre, cglib può migliorare le prestazioni da intercettazioni specializzate comeFixedValue
. Una volta ho scritto un riassunto di diversi intercettori per cglib . < / p>Differenze di prestazione
Proxy JDK sono implementati piuttosto ingenuamente con un solo dispatcher di intercettazione, il
InvocationHandler
. Ciò richiede un metodo virtuale in una spedizione a un'implementazione che non può essere sempre in linea. Cglib consente di creare codice di byte specializzato Cosa può a volte migliorare le prestazioni. Ecco alcuni confronti per l'implementazione di un'interfaccia con 18 metodi 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 graffe. Puoi trovare maggiori dettagli sul benchmark in Byte Buddy's Tutorial , dove Byte Buddy è un'alternativa più moderna a cglib. Inoltre, notare che cglib non è più in uno sviluppo attivo.
Proxy dinamico: Implementazioni dinamiche delle interfacce in runtime utilizzando JDK API di riflessione .
Esempio: Spring utilizza i proxy dinamici per le transazioni come segue:
Il proxy generato viene sopra il fagiolo. Aggiunge un comportamento transnazionale al fagiolo. Qui il proxy genera dinamicamente in fase di esecuzione utilizzando API di riflessione JDK.
Quando un'applicazione viene fermata, il proxy verrà distrutto e avremo solo interfaccia e fagioli sul file system.
.
Nell'esempio sopra abbiamo un'interfaccia. Ma nella maggior parte dell'attuazione dell'interfaccia non è il migliore. Quindi il bean non implementa un'interfaccia, in tal caso, usiamo l'ereditarietà:
Per generare tali proxy, la primavera utilizza una biblioteca di terze parti chiamata cglib .
cglib ( c ode g energia lib rary) è integrata in cima a ASM , questo è utilizzato principalmente il fagiolo generato proxy proxy e aggiunge il comportamento del bean nei metodi proxy.
dalla documentazione di primavera :
.Spring AOP utilizza i proxy dinamici JDK o il cglib per creare il proxy per un dato oggetto bersaglio. (I proxy dinamici JDK sono preferiti Ogni volta che hai una scelta).
Se l'oggetto bersaglio da presentare implementa almeno un'interfaccia Quindi verrà utilizzato un proxy dinamico JDK. Tutte le interfacce Implementato dal tipo di destinazione sarà provocato. Se l'oggetto bersaglio Non implementa alcuna interfaccia, verrà creata un proxy cglib.
Se si desidera forzare l'uso del proxying cglib (ad esempio, al proxy Ogni metodo definito per l'oggetto bersaglio, non solo quelli implementati dalle sue interfacce) puoi farlo. Tuttavia, ci sono alcuni problemi a Considera:
I metodi finali non possono essere consigliati, in quanto non possono essere sovrascriviti.
Avrai bisogno dei binari di cglib 2 sul tuo classpath, mentre Dynamic I proxy sono disponibili con il JDK. La primavera ti avverterà automaticamente Quando ha bisogno di cglib e le classi della biblioteca di cglib non si trovano sul classpath.
Il costruttore del tuo oggetto proxied verrà chiamato due volte. Questo è un Conseguenza naturale del modello proxy cglib in cui una sottoclasse è Generato per ogni oggetto proxied. Per ogni istanza proxied, due Gli oggetti vengono creati: l'oggetto proxed effettivo e un'istanza del sottoclasse che implementa il consiglio. Questo comportamento non è esposto quando si utilizzano proxy JDK. Di solito, chiamando il costruttore del il tipo proxied due volte, non è un problema, come di solito ci sono solo Assegnazioni che si svolgono e nessuna logica reale è implementata nel Costruttore.