Как вводить бобы Hk2 с помощью Guice

Существует приложение dropwizard на основе трикотажа. Я переписал определения bean-компонентов Hk2 в Guice, и теперь я могу внедрить bean-компоненты Guice в ресурсы Джерси, но я заметил, что bean-компоненты Hk2, определенные в пакетах dropwizard, которые я не могу переписать, не видны Guice и не могут внедрить зависимости, определенные в Hk2.
Guice не видит bean-компонентов, определенных в пакетах Hk2, и Guice по умолчанию создает новые неинициализированные bean-компоненты. Я отключил это поведение с помощью requireExplicitBindings.

Я экспериментировал с HK2IntoGuiceBridge, но его сопоставление не вызывается для интересующих меня bean-компонентов. ConfiguredBundleX находится во внешнем артефакте.

Я пытался скопировать и перевести определения bean из пакетов и застрял на jersey bean Provider<ContainerRequest>, я понятия не имею, откуда это взялось.

public class ConfiguredBundleX implements ConfiguredBundle<MyAppConf> {
  public void run(T configuration, Environment environment) throws Exception {
    environment.jersey().register(new AbstractBinder() {
            protected void configure() {
                this.bind(new MyHk2Bean()).to(MyHk2Bean.class);
            }
        });
  }  
}

public class DependsOnHk2Bean { @Inject public DependsOnHk2Bean(MyHk2Bean b) {} }

public class MainModule extends AbstractModule {
    private final ServiceLocator locator;
    protected void configure() {
      binder().requireExplicitBindings();

      install(new HK2IntoGuiceBridge(locator));
      bind(DependsOnHk2Bean.class);
}

public class GuiceFeature implements Feature {
    public boolean configure(FeatureContext context) {
        ServiceLocator locator = ServiceLocatorProvider.getServiceLocator(context);
        GuiceBridge.getGuiceBridge().initializeGuiceBridge(locator);
        Injector injector = Guice.createInjector(
                new HK2IntoGuiceBridge(locator),
                new MainModule(locator));

        GuiceIntoHK2Bridge guiceBridge = locator.getService(GuiceIntoHK2Bridge.class);
        guiceBridge.bridgeGuiceInjector(injector);
        return true;
    }
}
// ...

 public void initialize(Bootstrap<X> bootstrap) {
   bootstrap.addBundle(new ConfiguredBundleX());
 }

 public void run(X config, Environment env) {
   env.jersey().register(new GuiceFeature());
 }

person Daneel Yaitskov    schedule 09.04.2020    source источник


Ответы (2)


К сожалению, в bean-компонентах Guice вы должны использовать @ HK2Inject, а не @Inject, чтобы внедрить bean-компоненты hk2 в Guice. Итак, в приведенном выше коде вы бы сделали:

public class DependsOnHk2Bean { @HK2Inject public DependsOnHk2Bean(MyHk2Bean b) {} }

Это из-за ограничений в guice (это может быть исправлено к настоящему времени), так что поведение @Inject не могло быть перезаписано

Я сам не пробовал приведенный выше код, поэтому не уверен, что он сработает, но это была сделка, когда был написан мост ...

См. HK2Inject и инъекция-hk2-services-в-guice-services

person jwells131313    schedule 09.04.2020
comment
Вам также может потребоваться использовать метод или поле инъекции. Я не могу вспомнить, работает ли @ HK2Inject с инъекцией конструктора! - person jwells131313; 09.04.2020

После раскопок Guice и HK2ToGuiceTypeListenerImpl я понял, что есть bindListener, чтобы перехватить отсутствующие привязки и вытащить их откуда-то. Код @HKInject есть, но я заметил, что слушатель не вызывается для некоторого bean-компонента, включая bean-компонент, который меня интересовал. Да, HKInject не поддерживает внедрение конструктора (версия 4.2.1)

Поэтому я решил вручную импортировать bean-компоненты HK и связать их в Guice. Терминология Dropwizard ужасна, есть методы для получения контекста, получение контекста администратора - это совершенно другое дело, и bean-компоненты должны быть получены с помощью метода getService!

@RequiredArgsConstructor
public class HkModule extends AbstractModule {
    private final ServiceLocator locator;

    @Override
    protected void configure() {
        binder().requireExplicitBindings();

        Provider<Bar> barProvider = locator.getService(
                new TypeLiteral<Provider<Bar>>(){}.getType());
        bind(Bar.class).toProvider(barProvider);
        bind(Foo.class).toInstance(locator.getService(Foo.class));
    }
}

person Daneel Yaitskov    schedule 10.04.2020