Полезность динамических прокси Java против обычных прокси - PullRequest
14 голосов
/ 12 сентября 2010

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

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

Варианты использования

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

Остальные?

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

  • Декоратор: регистрирует все вызовы методов, например,

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;
     }
} 

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

Заключение

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

Ответы [ 3 ]

12 голосов
/ 13 сентября 2010

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

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

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

11 голосов
/ 12 сентября 2010

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

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

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

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

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

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

...