繁体   English   中英

如何在Jersey 2中禁用依赖注入?

[英]How to Disable Dependency Injection in Jersey 2?

我不熟悉使用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依赖关系,因为它看到了与Guice相同的@Inject注释。

我不希望泽西岛做任何依赖注入。 我认为从Jersey到Guice有桥梁,但根据我在这里无法显示的程序要求,我需要自己创建REST控制器实例并向Guice Injector询问它们。

我的问题:如何在Jersey中禁用依赖注入?

我目前正在使用javax.inject.Inject注释。 也许我可以使用com.google.inject.Inject注释,认为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,因此注册部分是相同的。

你在这里遇到两个困境:

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

所以,我上面的解决方案做了以下事情:

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

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

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

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

Hiope有帮助,

干杯! 阿图尔

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM