Подтвердить что ты не робот

Полезность динамических прокси-серверов Java и обычных прокси-серверов

Мне нужен совет, какие сценарии динамический прокси оказался бы более полезным, чем обычный прокси.

Я приложил много усилий, чтобы научиться эффективно использовать динамические прокси. В этом вопросе следует отметить, что такие структуры, как AspectJ, могут выполнять в основном все, что мы пытаемся достичь с помощью динамических прокси, или, например, CGLIB можно использовать для устранения некоторых недостатков динамических прокси.

Использовать случаи

  • Декораторы - например, выполнять ведение журнала при вызове метода или возвращаемые кешем значения сложных операций
  • Подтверждение контракта. То есть, убедитесь, что параметры находятся в допустимом диапазоне, а типы возврата соответствуют принятым значениям.
  • Адаптер - увидел какую-нибудь умную статью где-то, описывающую, как это полезно. Тем не менее, я редко встречаю этот шаблон дизайна.

Другие?

Преимущества динамического прокси-сервера

  • Decorator: регистрировать все вызовы методов, например,

public Object invoke(Object target, Method method, Object[] arguments) {
         System.out.println("before method " + method.getName());
         return method.invoke(obj, args);
     }
}

Шаблон декоратора определенно полезен, так как он позволяет использовать побочные эффекты для всех методов прокси (хотя это поведение является примером для использования аспектов...).

  • Контракт: в отличие от обычного прокси, нам не нужно реализовывать полный интерфейс. Например.,

public Object invoke(Object target, Method method, Object[] arguments) {
     if ("getValues".equals(method.getName()) {
         // check or transform parameters and/or return types, e.g., 
         return RangeUtils.validateResponse( method.invoke(obj, args) );
     }

     if ("getVersion".equals(method.getName()) {
         // another example with no delegation
         return 3;
     }
} 

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

Заключение

Итак, я вижу здесь один реальный случай использования и один сомнительный прецедент. Что вы думаете?

4b9b3361

Ответ 1

Существует множество потенциальных применений для динамических прокси-серверов, выше описанных вами -

  • Публикация событий - по методу x(), прозрачно вызовите y() или отправьте сообщение z.
  • Управление транзакциями (для соединений db или других транзакционных операций)
  • Управление потоками - прозрачная обработка дорогостоящих операций.
  • Отслеживание производительности - операции синхронизации, проверенные, например, CountdownLatch.
  • Управление подключением - мышление API, например Salesforce Enterprise API, требующее от клиентов своей службы запуска сеанса перед выполнением любых операций.
  • Изменение параметров метода - если вы хотите передать значения по умолчанию для нулей, если это что-то вроде этого.

Это всего лишь несколько опций в дополнение к проверке и регистрации, как описано выше. FWIW, JSR 303, спецификация валидации bean, имеет реализацию AOP-стиля в Hibernate Validator, поэтому вам не нужно ее реализовывать специально для ваших объектов данных. Структура Spring также имеет встроенную валидацию и имеет действительно приятную интеграцию с AspectJ для некоторых описанных здесь вещей.

Ответ 2

Действительно, АОП использует большинство динамических прокси. Это потому, что вы можете создать динамический прокси-сервер вокруг объекта, который вы не знаете заранее.

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

Также обратите внимание, что Adapter and Decorator - это отдельные шаблоны. Они выглядят как шаблон прокси в том виде, в котором они реализованы (по композиции объекта), но они служат другой цели:

  • шаблон декоратора позволяет вам иметь несколько бетонных декораторов, тем самым добавляя функциональность во время выполнения
  • шаблон адаптера предназначен для адаптации объекта к интерфейсу unmatching. Лучший пример, который я могу придумать, - это EnumetationIterator - он адаптирует интерфейс Enumeration к интерфейсу Iterator.

Ответ 3

Другим вариантом использования, о котором я могу думать, является динамическое внедрение интерфейсов во время выполнения, что и работает с некоторыми фреймворками.

Возьмите, например, Retrofit, библиотеку Java для использования служб REST. Вы определяете интерфейс Java, который отражает операции, доступные в REST API, и украшайте методы аннотациями для настройки специфики запроса. Легко видеть, что в этом случае все методы, определенные в интерфейсе, должны выполнять HTTP-запрос на каком-либо сервере, преобразовывать аргументы метода в параметры запроса; и затем проанализировать ответ в объект java, определенный как возвращаемый тип метода.