Dalam hal Pola Desain Proxy , Apa perbedaan antara Dynamic Proxy JDK dan API pembuatan kode dinamis pihak ketiga seperti CGLib ?
Apa perbedaan antara menggunakan kedua pendekatan tersebut dan kapan satu harus memilih satu dari yang lain?
java
reflection
cglib
dynamic-proxy
KDjava
sumber
sumber
Jawaban:
JDK Dynamic proxy hanya dapat proxy dengan antarmuka (sehingga kelas target Anda perlu mengimplementasikan antarmuka, yang kemudian juga diimplementasikan oleh kelas proxy).
CGLIB (dan javassist) dapat membuat proxy dengan mensubclassing. Dalam skenario ini proksi menjadi subkelas dari kelas target. Tidak perlu antarmuka.
Jadi proksi Java Dynamic dapat proksi:
public class Foo implements iFoo
tempat CGLIB dapat proksi:public class Foo
EDIT:
Saya harus menyebutkan bahwa karena javassist dan CGLIB menggunakan proxy dengan mensubclassing, bahwa ini adalah alasan Anda tidak dapat mendeklarasikan metode final atau membuat kelas final saat menggunakan kerangka kerja yang mengandalkan ini. Itu akan menghentikan perpustakaan ini dari memungkinkan untuk subkelas kelas Anda dan menimpa metode Anda.
sumber
Perbedaan fungsionalitas
Proxy JDK memungkinkan untuk mengimplementasikan set antarmuka apa pun saat subkelas
Object
. Metode antarmuka apa pun, plusObject::hashCode
,Object::equals
danObject::toString
kemudian diteruskan keInvocationHandler
. Selain itu, antarmuka perpustakaan standarjava.lang.reflect.Proxy
diterapkan.cglib memungkinkan Anda untuk mengimplementasikan set antarmuka apa pun saat subkelas kelas non-final. Juga, metode dapat diganti secara opsional, yaitu tidak semua metode non-abstrak perlu dicegat. Selain itu, ada berbagai cara menerapkan metode. Ia juga menawarkan
InvocationHandler
kelas (dalam paket yang berbeda), tetapi juga memungkinkan untuk memanggil metode super dengan menggunakan pencegat yang lebih canggih seperti misalnya aMethodInterceptor
. Selain itu, cglib dapat meningkatkan kinerja dengan intersepsi khusus sepertiFixedValue
. Saya pernah menulis ringkasan pencegat berbeda untuk cglib .Perbedaan kinerja
Proxy JDK diimplementasikan agak naif dengan hanya satu operator intersepsi, yang
InvocationHandler
. Ini membutuhkan pengiriman metode virtual ke implementasi yang tidak selalu dapat disatukan. Cglib memungkinkan untuk membuat kode byte khusus yang terkadang dapat meningkatkan kinerja. Berikut adalah beberapa perbandingan untuk mengimplementasikan antarmuka dengan metode 18 rintisan:Waktu dicatat dalam nanodetik dengan standar deviasi dalam kawat gigi. Anda dapat menemukan rincian lebih lanjut tentang tolok ukur dalam tutorial Byte Buddy, di mana Byte Buddy adalah alternatif yang lebih modern untuk cglib. Juga, perhatikan bahwa cglib tidak lagi dalam pengembangan aktif.
sumber
Dynamic proxy: Implementasi dinamis dari antarmuka saat runtime menggunakan JDK Reflection API .
Contoh: Spring menggunakan proksi dinamis untuk transaksi sebagai berikut:
Proxy yang dihasilkan berada di atas kacang. Ini menambahkan perilaku transnasional pada kacang. Di sini proksi menghasilkan secara dinamis saat runtime menggunakan JDK Reflection API.
Ketika aplikasi dihentikan, proksi akan dihancurkan dan kami hanya akan memiliki antarmuka dan kacang pada sistem file.
Pada contoh di atas kita memiliki antarmuka. Tetapi dalam sebagian besar implementasi antarmuka tidak terbaik. Jadi bean tidak mengimplementasikan antarmuka, dalam hal ini kami menggunakan warisan:
Untuk menghasilkan proxy seperti itu, Spring menggunakan perpustakaan pihak ketiga yang disebut CGLib .
CGLib ( C ode G eneration Lib rary) dibangun di atas ASM , ini terutama digunakan menghasilkan proxy yang memperpanjang kacang dan menambahkan perilaku kacang dalam metode proxy.
Contoh untuk proxy JDK Dynamic dan CGLib
Ref musim semi
sumber
Dari dokumentasi Spring :
sumber