2012-05-19 4 views
94

В случае Proxy Design Pattern, а какая разница между JDK's Dynamic Proxy и интерфейсом API по обращению с динамическим кодом стороннего разработчика, например CGLib?В чем разница между динамическим прокси JDK и CGLib?

В чем разница между использованием обоих подходов и когда следует выбирать один за другим?

+3

Получить код здесь: . В cglib вы можете создать прокси класса и прокси-сервер. Spring использует CGlib по умолчанию, в то время как AspectJ использует Java-прокси. Прочтите это также: http://jnb.ociweb.com/jnb/jnbNov2005.html;) –

ответ

127

JDK Динамический прокси-сервер может только прокси-интерфейс по интерфейсу (поэтому вашему целевому классу необходимо реализовать интерфейс, который затем также реализуется прокси-классом).

CGLIB (и javassist) может создавать прокси-сервер путем подкласса. В этом случае прокси становится подклассом целевого класса. Нет необходимости в интерфейсах.

Так Java Динамические прокси могут прокси: public class Foo implements iFoo где CGLIB может прокси: public class Foo

EDIT:

Следует отметить, что из-за Javassist и CGLIB использовать прокси на подклассы, что это причина, вы не можете объявить окончательный методы или сделать класс окончательным при использовании фреймворков, которые полагаются на это. Это помешало бы этим библиотекам позволить подклассифицировать ваш класс и переопределить ваши методы.

+0

tHANKS .. !! но было бы полезно, если бы вы могли дать мне один пример кода (или ссылку), чтобы проиллюстрировать его использование над другим в некотором случае .. !!! – KDjava

+3

Перечень кодов на http://www.edc4it.com/2011/11/03/jpa-transactional-proxy-for-javase/ создает прокси-сервер с использованием javassist. Здесь: http://www.edc4it.com/2011/03/01/using-run-time-bytecode-instrumentation-bci/ - пример использования CGLib. Пример использования прокси Java Dynamic можно найти http://docs.oracle.com/javase/1.3/docs/guide/reflection/proxy.html –

+0

код CGLIB - http://www.edc4it.com/2011/03/01/using-run-time-bytecode-instrumentation-bci/был действительно интересен и полезен тоже .. Большое спасибо. !! – KDjava

35

Различия в функциональности

  • Прокси JDK позволяют реализовать любой набор интерфейсов, а подклассов java.lang.reflect.Proxy. Любой метод интерфейса, плюс Object::hashCode, Object::equals и Object::toString затем направляется в InvocationHandler.

  • cglib позволяет реализовать любой набор интерфейсов при подклассификации любого не конечного класса. Кроме того, методы могут быть переопределены необязательно, то есть не все не абстрактные методы должны быть перехвачены. Кроме того, существуют различные способы реализации метода. Он также предлагает класс InvocationHandler (в другом пакете), но также позволяет вызывать супер методы с использованием более совершенных перехватчиков, например, MethodInterceptor. Кроме того, cglib может повысить производительность за счет специализированных перехватов, таких как FixedValue. Однажды я написал a summary of different interceptors for cglib.

Разница в производительности

JDK прокси реализованы довольно простодушно только один перехват диспетчером в InvocationHandler. Для этого требуется виртуальный метод отправки в реализацию, которая не всегда может быть встроена. Cglib позволяет создавать специализированный байтовый код, что иногда может улучшить производительность. Вот некоторые сравнения для реализации интерфейса с методами 18 окурка:

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

время отмечается в наносекунд со стандартным отклонением в фигурных скобках. Более подробную информацию об эталонном тестировании вы найдете в Byte Buddy's tutorial, где Byte Buddy - более современная альтернатива cglib. Также обратите внимание, что cglib больше не находится в активной разработке.

+1

Почему весенняя документация поддерживает JDK-проксирование через cglib, учитывая преимущества производительности последнего? http://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-proxying – P4ndaman

+1

Cglib является внешней зависимостью и в настоящее время не поддерживается. Опираясь на стороннее программное обеспечение, вы всегда играете в азартные игры, поэтому лучше всего, когда на это полагается как можно меньше людей. –

+0

* Это * должен быть принятым ответом! –

12

Динамический прокси: Динамические реализации интерфейсов во время выполнения с помощью JDK Reflection API.

Пример: Пружина использует динамические прокси для операций следующим образом:

enter image description here

Сгенерированный прокси приходит на вершине фасоли. Это добавляет транснациональное поведение к bean-компоненту. Здесь прокси генерирует динамически во время выполнения с использованием JDK Reflection API.

Когда приложение остановлено, прокси-сервер будет уничтожен, и у нас будет только интерфейс и компонент в файловой системе.


В приведенном выше примере у нас есть интерфейс. Но в большинстве случаев реализация интерфейса не самая лучшая. Так боб не реализует интерфейс, в этом случае мы используем наследование:

enter image description here

Для создания таких прокси, Spring использует библиотека третьей стороны называется CGLIB.

CGLIB (С ода G eneration Lib окон- чательно) построен на вершине ASM, это в основном используется в генерации прокси простирающуюся компонент и добавляет поведение фасоли в способах прокси.

Examples for JDK Dynamic proxy and CGLib

Spring ref

0

From Spring documentation:

Spring AOP использует либо JDK динамические прокси или CGLIB создать прокси-сервер для данного целевого объекта. (Динамические прокси-серверы JDK предпочтительнее всякий раз, когда у вас есть выбор).

Если целевой объект для проксирования реализует хотя бы один интерфейс, тогда будет использоваться динамический прокси JDK. Все интерфейсы, реализованные целевым типом, будут проксимизованы. Если целевой объект не реализует никаких интерфейсов, тогда будет создан прокси CGLIB.

Если вы хотите принудительно использовать прокси CGLIB (например, для проксирования каждого метода, определенного для целевого объекта, а не только для тех, которые реализованы его интерфейсами), вы можете это сделать. Тем не менее, есть некоторые вопросы, которые следует учитывать:

Окончательные методы не могут быть рекомендованы, так как они не могут быть переопределены.

Вам понадобятся бинарные файлы CGLIB 2 в вашем пути к классам, тогда как динамические прокси доступны в JDK. Spring автоматически предупредит вас, когда ему понадобится CGLIB, а классы библиотеки CGLIB не найдены в пути к классам.

Конструктор вашего прокси-объекта будет вызываться дважды. Это является естественным следствием прокси-модели CGLIB, при которой подкласс создается для каждого прокси-объекта. Для каждого проксированного экземпляра создаются два объекта: фактический прокси-объект и экземпляр подкласса, который реализует совет. Это поведение не отображается при использовании прокси JDK. Обычно вызов конструктора прокси-типа дважды не является проблемой, так как обычно обычно выполняются только назначения, и в конструкторе не реализована реальная логика.

Смежные вопросы