【问题标题】:How to Disable Dependency Injection in Jersey 2?如何在 Jersey 2 中禁用依赖注入?
【发布时间】:2016-11-10 16:11:09
【问题描述】:

我是使用 Jersey 2 创建 REST Web 服务的新手。我能够得到一些简单的案例,现在我正在继续“真正的”工作。

我创建了自己的 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 注释。

但是,当我运行上述代码来引导 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 注释,认为泽西岛不会寻找这些注释。但是,我还是宁愿在泽西岛关闭依赖注入。我该怎么做?

谢谢!!

【问题讨论】:

    标签: java jersey guice jersey-2.0 hk2


    【解决方案1】:

    首先,你的解决方案:

    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,所以注册部分是相同的。

    您在这里面临两个困境:

    1. Jersey DI 将尝试在您的对象中注入字段。那是因为它没有意识到有一个对象已经完成。它假定它必须注入字段。

    所以,我上面的解决方案如下:

    将 Guice bean 绑定到 jersey 环境。这将使 jersey 能够找到您创建的 bean。由于它绑定到 jersey env 中,它不会尝试重新初始化 bean,而是将其视为完全有效的对象。 为此,您需要将 Resource 注册为类参数(触发球衣搜索已注册的 bean,或在需要时创建一个)

    您可以做的另一个解决方案是将您的注入移动到构造函数(通常是避免字段注入的好做法)。因为你注册了一个对象,所以再次调用构造函数是非法的。因此球衣不会尝试做任何注射(因为没有什么可做的)

    最后,我不知道您的要求是如何工作的,但您想要做的基本上是手动创建 Guice-Jersey 桥。以你演示的方式教你的 bean 到球衣上,这正是 Guice-Jersey 桥所做的,除了它修复了所有那些小的边缘情况(就像你现在看到的那样)。强烈建议您实现该桥。

    该桥实际上只是简单地将 bean 的创建委托给 guice。这意味着它将(1)向 guice 请求一个实例,然后自己创建一个(如果 Guice 没有返回实例)。

    帮帮忙,

    干杯!阿图尔

    【讨论】:

    • 成功了,谢谢!!对于那些阅读,我的一个快速技巧是使用com.google.inject.Inject 注释而不是标准的javax.inject.Inject 注释。但是,我仍然想要一个基于 Jersey 的解决方案。在我的特殊情况下,上述代码中的JerseyEnvironment 实际上是ResourceConfig 的一个实例,但所有必要的方法都存在。奇怪的是,泽西岛没有禁用 DI 的开关。一个类绑定到一个实例也很奇怪;通常情况正好相反。不管怎样,谢谢!!
    • 这对 Dagger 有什么作用? stackoverflow.com/q/49221066/942671
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-02
    • 2013-04-19
    相关资源
    最近更新 更多