Guice: привязка интерфейса к экземпляру, созданному динамическими прокси

#java #dynamic #proxy #guice

#java #динамический #прокси #guice

Вопрос:

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

 interface ITaggingInterface() {
}

interface ISubInterface extends ITaggingInterface {
  String doSomething();
}
 

ISubInterface может быть реализован с помощью прокси:

 ISubInterface si = (ISubInterface)Proxy.newProxyInstance(classloader, new Class<?>[]{ISubInterface.class}, invocationHandler);
 

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

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

 bind(any-sub-interface).toProvider(provider-that-creates-proxy-instance);
 

Возможно ли это с помощью guice?

Ответ №1:

Я не верю, что это возможно так, как вы ищете. По сути, привязки Guice похожи на Map<Key, Provider> . Это затрудняет привязку «любого типа с этой аннотацией», «любого подтипа этого типа» или других подобных привязок, подобных сопоставлению.

Если вы согласны с использованием метода / ввода поля и пользовательской аннотации вместо @Inject, вы можете попробовать использовать пользовательскую инъекцию, которая позволит вам проверять введенные классы и манипулировать ими по мере необходимости так, как это делает приведенная выше ссылка с @InjectLogger .

Помимо реструктуризации ваших требований, мое личное решение было бы примерно таким:

 /** Injectable. */
class TaggingInterfaceFactory {
  /** Guice can always inject the injector. */
  @Inject Injector injector;

  <T> T getInstanceOrProxy(Class<T> clazz) {
    if (clazz.isAssignableFrom(ITaggingInterface.class)) {
      return createYourProxyHere(clazz);
    } else {
      return injector.getInstance(clazz);
    }
  }
}