英文:
How inject Hk2 beans with Guice
问题
以下是翻译好的部分:
有一个Dropwizard应用程序,基于Jersey框架。我将Hk2的bean定义重写为Guice,并且现在我可以将Guice的bean注入到Jersey资源中,但我注意到在Dropwizard捆绑包中定义的Hk2 bean(我无法重写)对Guice不可见,因此无法注入Hk2中定义的依赖关系。Guice无法看到在Hk2捆绑包中定义的bean,并且默认情况下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());
}
如果还有其他需要帮助的地方,请随时提问。
英文:
There is a dropwizard app, which is jersey based.
I rewrote Hk2 bean definitions into Guice and now I can inject Guice beans into Jersey Resources,
but I noticed that Hk2 beans, defined in dropwizard bundles, which I cannot rewrite, are not
visible by Guice and it fails to inject dependencies defined in Hk2.
Guice doesn't see beans defined in Hk2 bundles and Guice creates new uninitialized beans by default.
I disabled this behavior with requireExplicitBindings.
I experimented with HK2IntoGuiceBridge, but its matcher is not invoked for beans I am interested in.
ConfiguredBundleX is located in external artifact.
I tried to copy and translate bean definitions from bundles and stuck with jersey bean Provider<ContainerRequest>
, I have no idea where it comes from.
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());
}
答案1
得分: 0
很不幸,在Guice中,您必须使用@HK2Inject而不是@Inject来将hk2 bean注入到Guice中。因此,在您上面的代码中,您将执行以下操作:
public class DependsOnHk2Bean {
@HK2Inject
public DependsOnHk2Bean(MyHk2Bean b) {}
}
这是因为在Guice中存在限制(可能已经修复),无法覆盖@Inject的行为。
我自己尚未尝试过上述代码,所以我不确定它是否会起作用,但在编写此桥接器时,情况就是如此...
参见HK2Inject和injecting-hk2-services-into-guice-services。
英文:
Unfortunately in Guice beans you have to use @HK2Inject rather than @Inject in order to inject hk2 beans into Guice. So in your code above you would do:
public class DependsOnHk2Bean { @HK2Inject public DependsOnHk2Bean(MyHk2Bean b) {} }
This is because of limitation in guice (it may be fixed by now) such that @Inject behavior could not overwritten
I have not tried the above code myself so I'm not sure it'll work, but that was the deal back when the bridge was written...
See HK2Inject and injecting-hk2-services-into-guice-services
答案2
得分: 0
在研究了Guice和HK2ToGuiceTypeListenerImpl之后,我发现有一个bindListener方法,可以用来拦截缺失的绑定并从其他地方获取它们。虽然存在@HKInject代码,但我注意到某些bean(包括我感兴趣的bean)并未触发监听器。是的,HKInject不支持构造函数注入(版本为4.2.1)。
因此,我决定手动导入HK beans并在Guice中进行绑定。
Dropwizard的术语非常混乱,有一些方法涉及到获取上下文等内容,而获取管理员上下文则完全不同,必须使用getService方法来获取beans!
@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));
}
}
英文:
After digging Guice and HK2ToGuiceTypeListenerImpl I figured out that there is bindListener to kind of intercept missing bindings and pull them from somewhere. @HKInject code is there, but I noticed that the listener is not called for some bean including the bean I was interested in. Yes HKInject doesn't support constructor injection (4.2.1 version)
So I decided to manually import HK beans and bind them in Guice.
Dropwizard terminology is horrible there are methods get context something, get admin context is totally something different and beans must be get with getService method!
@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));
}
}
专注分享java语言的经验与见解,让所有开发者获益!
评论