JDK dinamik proxy ve CGLib arasındaki fark nedir?


147

Proxy Tasarım Deseni durumunda, JDK'nın Dinamik Proxy'si ile CGLib gibi üçüncü taraf dinamik kod oluşturma API'leri arasındaki fark nedir ?

Her iki yaklaşımı da kullanmak arasındaki fark nedir ve ne zaman biri diğerini tercih etmelidir?


3
Kodu buradan alın: < gist.github.com/ksauzz/1563486 >. Cglib'de hem sınıf proxy'si hem de arabirim proxy'si oluşturabilirsiniz. AspectJ Java proxy'sini kullanırken Spring varsayılan olarak CGlib kullanır. Bunu da okuyun: jnb.ociweb.com/jnb/jnbNov2005.html ;)
Ray

Yanıtlar:


185

JDK Dinamik proxy yalnızca arabirime göre proxy yapabilir (bu nedenle hedef sınıfınızın, daha sonra proxy sınıfı tarafından uygulanan bir arabirim uygulaması gerekir).

CGLIB (ve javassist) alt sınıflandırma yoluyla bir proxy oluşturabilir. Bu senaryoda, proxy hedef sınıfın bir alt sınıfı olur. Arayüzlere gerek yok.

Java Dynamic proxy'leri proxy yapabilir: public class Foo implements iFooburada CGLIB proxy yapabilir:public class Foo

DÜZENLE:

Javassist ve CGLIB'nin alt sınıflandırma yoluyla proxy kullandıkları için, buna dayanarak çerçeveler kullanırken son yöntemleri bildirememenizin veya sınıfı final yapamamanızın nedeni olduğunu belirtmeliyim. Bu, bu kütüphanelerin sınıfınızı alt sınıflara ayırmasına ve yöntemlerinizi geçersiz kılmasına izin vermez.


Teşekkürler..!! ama bir durumda başka birinin üzerinde kullanımını göstermek için bana bir örnek kod (veya Link) verebilirseniz yararlı olacaktır .. !!!
KDjava

1
JDK proxy'lerinin aslında herhangi bir Foo türü için değil, IFoo'nun proxy'sini aldattığını unutmayın. Bu oldukça önemli bir ayrım. Ayrıca, cglib proxy'leri tam alt sınıflardır - bundan yararlanın! Filtreleri yalnızca önem verdiğiniz proxy yöntemlerini kullanın ve oluşturulan sınıfı doğrudan kullanın.
lscoughlin

9
CGLib alt sınıfı oluşturma işleminin, doğru kurucu ile doğru argümanları çağırabilmek için süper sınıf hakkında yeterli bilgiye sahip olmayı gerektirdiğine dikkat edilmelidir. Arabirim tabanlı proxy'den farklı olarak kurucuları önemsemiyor. Bu CGLib proxy'leriyle çalışmayı JDK proxy'lerinden daha az "otomatik" yapar. Bir diğer ayrım "yığın" maliyetidir. Bir JDK proxy'si her zaman çağrı başına ek yığın karelerine maruz kalırken, CGLib herhangi bir ek yığın karesine mal olmayabilir. Bu, uygulama ne kadar karmaşık hale geldikçe giderek daha alakalı hale gelir (çünkü yığın ne kadar büyük olursa, daha fazla bellek iş parçacığı tüketir).
Ray

1
cglib nihai yöntemleri temsil edemez, ancak istisna atmaz gist.github.com/mhewedy/7345403cfa52e6f47563f8a204ec0e80
Muhammad Hewedy

Evet, CGLIB nihai yöntemleri görmezden gelir.
yashjain12yj

56

İşlev farklılıkları

  • JDK proxy'leri, alt sınıflandırma sırasında herhangi bir arabirim kümesinin uygulanmasına izin verir Object. Herhangi bir arabirim yöntemi ve Object::hashCode, Object::equalsve Object::toStringdaha sonra bir iletilir InvocationHandler. Ayrıca, standart kitaplık arabirimi java.lang.reflect.Proxyuygulanır.

  • cglib, herhangi bir son sınıf olmayan sınıfın alt sınıfını yaparken herhangi bir arabirim kümesini uygulamanıza olanak tanır. Ayrıca, yöntemler isteğe bağlı olarak geçersiz kılınabilir, yani soyut olmayan tüm yöntemlerin ele geçirilmesi gerekmez. Ayrıca, bir yöntemi uygulamanın farklı yolları vardır. Ayrıca bir InvocationHandlersınıf (farklı bir pakette) sunar, ancak a gibi daha gelişmiş önleyicileri kullanarak süper yöntemleri çağırmaya da izin verir MethodInterceptor. Ayrıca, cglib gibi özel müdahalelerle performansı artırabilir FixedValue. Bir keresinde cglib için farklı önleyicilerin bir özetini yazdım .

Performans farklılıkları

JDK vekil sunucuları sadece tek bir müdahale görevlisi ile oldukça naif bir şekilde uygulanır InvocationHandler. Bu, her zaman satır içine alınamayan bir uygulamaya sanal yöntem gönderilmesini gerektirir. Cglib bazen performansı artırabilecek özel bayt kodu oluşturmaya izin verir. 18 saplama yöntemiyle bir arayüz uygulamak için bazı karşılaştırmalar:

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

Zaman, parantezlerde standart sapma ile nanosaniye cinsinden not edilir. Bente Buddy'nin cglib'e daha modern bir alternatif olduğu Byte Buddy'nin eğitiminde karşılaştırmalı değerlendirme hakkında daha fazla ayrıntı bulabilirsiniz . Ayrıca, cglib'in artık aktif geliştirme altında olmadığını unutmayın.


2
İlkbahar dokümantasyonu, ikincisinin performans faydaları göz önüne alındığında neden cglib üzerinden JDK proxy'sini destekliyor? docs.spring.io/spring/docs/2.5.x/reference/…
P4ndaman

2
Cglib harici bir bağımlıdır ve şu anda desteklenmemektedir. Üçüncü taraf yazılımlara güvenmek her zaman bir kumardır, bu yüzden mümkün olduğunca az kişi buna güveniyorsa en iyisidir.
Rafael Winterhalter

Blogunuzda şunları söylersiniz: "Ancak, InvocationHandler # invoke yöntemiyle gelen proxy nesnesinde bir yöntem çağırırken dikkatli olmalısınız. Bu yöntemdeki tüm çağrılar aynı InvocationHandler ile gönderilir ve bu nedenle sonsuz bir döngüye neden olabilir ." Ne demek istiyorsun?
Koray Tugay

Proxy nesnesinde bir yöntem çağırırsanız, çağrı işleyicimiz olan herhangi bir çağrı yönlendirilir. Herhangi bir çağırma işleyicisi çağrısı nesneye yapılan bir çağrıyı devrederse, belirtilen özyineleme gerçekleşir.
Rafael Winterhalter

Merhaba Rafael, cevabınızla ilgisiz mesaj, 5 yıl önce yapılan bir düzenleme hakkında size ping atıyorum . As CGLIB görünüşte hala 2019 yılında kaydedilmesini vardır ve herhangi göstermiyor tutuklandı gelişimini kendi Benioku'da, ben ettik ifadenizi kaldırıldı etiket alıntı gelen. Söz konusu bir şey varsa etiket açıklamasını / alıntısını geliştirmekten çekinmeyin.
Cur

28

Dinamik proxy: JDK Reflection API'sı kullanılarak çalışma zamanında arabirimlerin dinamik uygulamaları .

Örnek: Spring, işlemler için aşağıdaki gibi dinamik proxy'ler kullanır:

resim açıklamasını buraya girin

Oluşturulan vekil fasulye üstüne gelir. Fasulyeye ulusötesi davranış ekler. Burada proxy JDK Reflection API kullanarak çalışma zamanında dinamik olarak üretir.

Bir uygulama durdurulduğunda, proxy yok edilir ve dosya sisteminde yalnızca arayüz ve fasulye bulunur.


Yukarıdaki örnekte arayüz var. Ancak arayüzün uygulanmasında çoğu iyi değildir. Yani fasulye bir arayüz uygulamıyor, bu durumda kalıtım kullanıyoruz:

resim açıklamasını buraya girin

Bu tür vekil sunucuları oluşturmak için Spring, CGLib adında bir üçüncü taraf kütüphanesi kullanır .

CGLib ( K ode G eneration Lib rary ) ASM üzerine inşa edilmiştir , bu temel olarak proxy genişletme fasulye oluşturmak için kullanılır ve proxy yöntemlerinde fasulye davranışı ekler.

JDK Dinamik proxy ve CGLib örnekleri

Bahar ref


5

İlkbahar dokümanlarından :

Spring AOP, belirli bir hedef nesne için proxy oluşturmak üzere JDK dinamik proxy'lerini veya CGLIB'yi kullanır. (JDK dinamik proxy'leri tercihiniz olduğunda tercih edilir).

Yakınlaştırılacak hedef nesne en az bir arabirim uygularsa, bir JDK dinamik proxy'si kullanılır. Hedef tür tarafından uygulanan tüm arabirimler proxy üzerinden oluşturulacaktır. Hedef nesne herhangi bir arabirim uygulamazsa bir CGLIB proxy'si oluşturulur.

CGLIB proxy'nin kullanımını zorlamak istiyorsanız (örneğin, yalnızca arabirimleri tarafından uygulananları değil, hedef nesne için tanımlanan her yöntemi proxy yapmak için) bunu yapabilirsiniz. Bununla birlikte, dikkate alınması gereken bazı hususlar vardır:

geçersiz kılınamayacakları için nihai yöntemler önerilemez.

Sınıf yolunuzda CGLIB 2 ikili dosyalarına ihtiyacınız olurken JDK ile dinamik proxy'ler kullanılabilir. Bahar, CGLIB gerektiğinde sizi otomatik olarak uyarır ve CGLIB kütüphane sınıfları sınıf yolunda bulunmaz.

Proxy nesnenizin kurucusu iki kez çağrılır. Bu, her proxy nesnesi için bir alt sınıfın oluşturulduğu CGLIB proxy modelinin doğal bir sonucudur. Her proxy örneği için iki nesne oluşturulur: gerçek proxy nesne ve öneriyi uygulayan alt sınıf örneği. JDK proxy'leri kullanılırken bu davranış gösterilmez. Genellikle, proxy türünün yapıcısını iki kez çağırmak bir sorun değildir, çünkü genellikle sadece atamalar yapılır ve kurucuya gerçek bir mantık uygulanmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.