如何在 Jersey 2 中禁用依赖注入?
How to Disable Dependency Injection in Jersey 2?
我是使用 Jersey 2 创建 REST Web 服务的新手。我能够处理一些简单的案例,现在我要继续 "real" 工作。
我创建自己的 ResourceConfig
实例并使用 Guice 返回的 REST 控制器实例填充 ResourceConfig
实例:
<!-- language: lang-java -->
final ResourceConfig rc = new ResourceConfig();
//register an *instance* of a REST controller
rc.register(injector.getInstance(MyRestController.class));
请注意,由于这些 REST 控制器实例是由 Guice 提供的,因此实例中填充了所有必要的依赖项,这些依赖项标有 @Inject
注释。
但是,当我 运行 上面的代码到 bootstrap Jersey 时,我看到如下错误:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(....
显然发生的事情是 Jersey 也在 尝试解决对 REST 控制器实例的 @Inject
依赖关系,因为它看到相同的 @Inject
Guice 所做的注释。
我不想让 Jersey 做任何依赖注入。我认为有从 Jersey 到 Guice 的桥梁,但基于我无法在此处显示的程序要求,我需要自己创建 REST 控制器实例并向 Guice Injector
询问它们。
我的问题:如何在 Jersey 中禁用依赖注入?
我目前正在使用 javax.inject.Inject
注释。也许我可以改用 com.google.inject.Inject
注释,因为我认为 Jersey 不会寻找这些注释。但是,我还是宁愿关闭 Jersey 中的依赖注入。我该怎么做?
谢谢!!
首先,您的解决方案:
public class GuiceJerseyManualBridge extends io.dropwizard.Application<Configuration> {
@Override
public void run(Configuration configuration, Environment environment) throws Exception {
JerseyEnvironment jersey = environment.jersey();
// create the Guice env and its dependencies
Injector i = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
Map<String, String> props = new HashMap<>();
props.put("testme", "Hello World Guice Inject Test");
Names.bindProperties(binder(), props);
bind(HelloResource.class).in(Singleton.class);
}
});
// get instance
HelloResource resourceInstance = i.getInstance(HelloResource.class);
jersey.register(new AbstractBinder() {
@Override
protected void configure() {
// teach jersey about your guice dependency
bind(resourceInstance).to(HelloResource.class);
}
});
jersey.register(HelloResource.class); // register resource - jersey will discover this from the binding
}
@Override
public void initialize(Bootstrap<Configuration> bootstrap) {
super.initialize(bootstrap);
}
public static void main(String[] args) throws Exception {
new GuiceJerseyManualBridge().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test2.yaml");
}
@Path("test")
@Produces(MediaType.APPLICATION_JSON)
public static class HelloResource {
@Inject
@Named("testme")
private String testString;
public HelloResource() {
System.err.println("I am created now");
}
@GET
@Path("test")
public String test(String x) {
return testString;
}
}
}
请忽略我的 DropWizard 设置。它使用 Jersey 并使用 Guice,因此注册部分是相同的。
您在这里面临两个困境:
- Jersey DI 将尝试在您的对象中注入字段。那是因为它没有意识到已经完成了一个对象。它假设它必须注入字段。
因此,我上面的解决方案执行以下操作:
将 Guice bean 绑定到 jersey 环境。这将使 jersey 能够找到您创建的 bean。因为它绑定到 jersey 环境中,所以它不会尝试重新初始化 bean,而是将其视为完全有效的对象。
为此,您需要将资源注册为 class 参数(触发 jersey 搜索已注册的 bean,或者在需要时创建一个)
您可以做的另一个解决方案是将您的注入移动到构造函数(通常是避免字段注入的良好做法)。因为你注册了一个对象,再次调用构造函数是不合法的。因此球衣不会尝试进行任何注射(因为有 none 要做)
最后,我不知道你的要求是如何工作的,但你想要做的基本上是手动创建一个 Guice-Jersey Bridge。以您演示的方式将 bean 教给 jersey 正是 Guice-Jersey 桥所做的,除了它修复了所有这些小的边缘情况(如您现在看到的那样)。强烈建议您实施该桥。
该桥的作用实际上是简单地将 bean 的创建委托给 guice。这意味着它将 (1) 向 guice 请求一个实例,然后自己创建一个实例(如果 Guice returns 没有实例)。
Hiope 有帮助,
干杯!阿图尔
我是使用 Jersey 2 创建 REST Web 服务的新手。我能够处理一些简单的案例,现在我要继续 "real" 工作。
我创建自己的 ResourceConfig
实例并使用 Guice 返回的 REST 控制器实例填充 ResourceConfig
实例:
<!-- language: lang-java -->
final ResourceConfig rc = new ResourceConfig();
//register an *instance* of a REST controller
rc.register(injector.getInstance(MyRestController.class));
请注意,由于这些 REST 控制器实例是由 Guice 提供的,因此实例中填充了所有必要的依赖项,这些依赖项标有 @Inject
注释。
但是,当我 运行 上面的代码到 bootstrap Jersey 时,我看到如下错误:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(....
显然发生的事情是 Jersey 也在 尝试解决对 REST 控制器实例的 @Inject
依赖关系,因为它看到相同的 @Inject
Guice 所做的注释。
我不想让 Jersey 做任何依赖注入。我认为有从 Jersey 到 Guice 的桥梁,但基于我无法在此处显示的程序要求,我需要自己创建 REST 控制器实例并向 Guice Injector
询问它们。
我的问题:如何在 Jersey 中禁用依赖注入?
我目前正在使用 javax.inject.Inject
注释。也许我可以改用 com.google.inject.Inject
注释,因为我认为 Jersey 不会寻找这些注释。但是,我还是宁愿关闭 Jersey 中的依赖注入。我该怎么做?
谢谢!!
首先,您的解决方案:
public class GuiceJerseyManualBridge extends io.dropwizard.Application<Configuration> {
@Override
public void run(Configuration configuration, Environment environment) throws Exception {
JerseyEnvironment jersey = environment.jersey();
// create the Guice env and its dependencies
Injector i = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
Map<String, String> props = new HashMap<>();
props.put("testme", "Hello World Guice Inject Test");
Names.bindProperties(binder(), props);
bind(HelloResource.class).in(Singleton.class);
}
});
// get instance
HelloResource resourceInstance = i.getInstance(HelloResource.class);
jersey.register(new AbstractBinder() {
@Override
protected void configure() {
// teach jersey about your guice dependency
bind(resourceInstance).to(HelloResource.class);
}
});
jersey.register(HelloResource.class); // register resource - jersey will discover this from the binding
}
@Override
public void initialize(Bootstrap<Configuration> bootstrap) {
super.initialize(bootstrap);
}
public static void main(String[] args) throws Exception {
new GuiceJerseyManualBridge().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test2.yaml");
}
@Path("test")
@Produces(MediaType.APPLICATION_JSON)
public static class HelloResource {
@Inject
@Named("testme")
private String testString;
public HelloResource() {
System.err.println("I am created now");
}
@GET
@Path("test")
public String test(String x) {
return testString;
}
}
}
请忽略我的 DropWizard 设置。它使用 Jersey 并使用 Guice,因此注册部分是相同的。
您在这里面临两个困境:
- Jersey DI 将尝试在您的对象中注入字段。那是因为它没有意识到已经完成了一个对象。它假设它必须注入字段。
因此,我上面的解决方案执行以下操作:
将 Guice bean 绑定到 jersey 环境。这将使 jersey 能够找到您创建的 bean。因为它绑定到 jersey 环境中,所以它不会尝试重新初始化 bean,而是将其视为完全有效的对象。 为此,您需要将资源注册为 class 参数(触发 jersey 搜索已注册的 bean,或者在需要时创建一个)
您可以做的另一个解决方案是将您的注入移动到构造函数(通常是避免字段注入的良好做法)。因为你注册了一个对象,再次调用构造函数是不合法的。因此球衣不会尝试进行任何注射(因为有 none 要做)
最后,我不知道你的要求是如何工作的,但你想要做的基本上是手动创建一个 Guice-Jersey Bridge。以您演示的方式将 bean 教给 jersey 正是 Guice-Jersey 桥所做的,除了它修复了所有这些小的边缘情况(如您现在看到的那样)。强烈建议您实施该桥。
该桥的作用实际上是简单地将 bean 的创建委托给 guice。这意味着它将 (1) 向 guice 请求一个实例,然后自己创建一个实例(如果 Guice returns 没有实例)。
Hiope 有帮助,
干杯!阿图尔