W przypadku wzorca projektowego proxy , jaka jest różnica między dynamicznym proxy JDK a interfejsami API do generowania kodu dynamicznego innych firm, takimi jak CGLib ?
Jaka jest różnica między stosowaniem obu podejść i kiedy należy je preferować?
java
reflection
cglib
dynamic-proxy
KDjava
źródło
źródło
Odpowiedzi:
JDK Dynamiczne proxy może proxy tylko przez interfejs (więc Twoja klasa docelowa musi zaimplementować interfejs, który jest następnie implementowany przez klasę proxy).
CGLIB (i javassist) mogą tworzyć proxy przez tworzenie podklas. W tym scenariuszu proxy staje się podklasą klasy docelowej. Nie potrzeba interfejsów.
Więc dynamiczne proxy Java mogą proxy:
public class Foo implements iFoo
gdzie CGLIB może proxy:public class Foo
EDYTOWAĆ:
Powinienem o tym wspomnieć, ponieważ javassist i CGLIB używają proxy przez podklasy, że jest to powód, dla którego nie można zadeklarować ostatecznych metod ani uczynić klasy ostateczną, gdy używa się frameworków, które na tym polegają. To powstrzymałoby te biblioteki przed zezwalaniem na podklasy twojej klasy i nadpisywanie twoich metod.
źródło
Różnice w funkcjonalności
Serwery proxy JDK pozwalają na implementację dowolnego zestawu interfejsów podczas tworzenia podklas
Object
. Dowolna metoda interfejsu plusObject::hashCode
,Object::equals
aObject::toString
następnie jest przekazywana do plikuInvocationHandler
. Dodatkowojava.lang.reflect.Proxy
zaimplementowano standardowy interfejs biblioteki .cglib umożliwia zaimplementowanie dowolnego zestawu interfejsów podczas tworzenia podklas dowolnej klasy, która nie jest ostateczna. Ponadto metody można opcjonalnie przesłonić, tj. Nie wszystkie metody nieabstrakcyjne muszą zostać przechwycone. Ponadto istnieją różne sposoby implementacji metody. Oferuje również
InvocationHandler
klasę (w innym pakiecie), ale pozwala również wywoływać super metody przy użyciu bardziej zaawansowanych przechwytywaczy, na przykład aMethodInterceptor
. Ponadto cglib może poprawić wydajność dzięki wyspecjalizowanym przechwyceniom, takim jakFixedValue
. Kiedyś napisałem podsumowanie różnych przechwytywaczy dla cglib .Różnice w wydajności
Serwery proxy JDK są implementowane raczej naiwnie z tylko jednym dyspozytorem przechwytywania, plikiem
InvocationHandler
. Wymaga to wysłania metody wirtualnej do implementacji, która nie zawsze może być wbudowana. Cglib pozwala na tworzenie wyspecjalizowanego kodu bajtowego, co czasami może poprawić wydajność. Oto kilka porównań implementacji interfejsu z 18 metodami pośredniczącymi:Czas jest podawany w nanosekundach z odchyleniem standardowym w szelkach. Więcej szczegółów na temat testu porównawczego można znaleźć w samouczku Byte Buddy, w którym Byte Buddy jest bardziej nowoczesną alternatywą dla cglib. Należy również zauważyć, że cglib nie jest już aktywnie rozwijany.
źródło
Dynamiczne proxy: dynamiczne implementacje interfejsów w czasie wykonywania przy użyciu JDK Reflection API .
Przykład: Spring używa dynamicznych proxy do transakcji w następujący sposób:
Wygenerowany proxy znajduje się na szczycie fasoli. Dodaje fasoli do międzynarodowego zachowania. Tutaj proxy generuje się dynamicznie w czasie wykonywania przy użyciu JDK Reflection API.
Kiedy aplikacja zostanie zatrzymana, proxy zostanie zniszczone, a my będziemy mieć tylko interfejs i bean w systemie plików.
W powyższym przykładzie mamy interfejs. Jednak w większości implementacji interfejs nie jest najlepszy. Więc bean nie implementuje interfejsu, w takim przypadku używamy dziedziczenia:
Aby wygenerować takie proxy, Spring używa biblioteki innej firmy o nazwie CGLib .
CGLib ( C ode G eneration Lib rary ) jest zbudowany na bazie ASM , jest używany głównie do generowania komponentu bean rozszerzającego proxy i dodaje zachowanie fasoli w metodach proxy.
Przykłady dla JDK Dynamic proxy i CGLib
Wiosna ref
źródło
Z dokumentacji Spring :
źródło