[英]How to make Jersey work with Dagger dependency injection?
Jersey 通常使用 HK2 依赖注入,但我想将 Jersey 与 Dagger 2 一起使用。Dagger 和 HK2 都实现了 JSR 330,我已经将其作为证据表明这应该可以不费吹灰之力。 我找到了使 Jersey 与 CDI(例如 Weld)、Spring DI 和 Guice 一起工作的方法,但我在 Dagger 上找不到任何东西。
提供一些上下文:我在 SE 环境中运行 Grizzly-Jersey 服务器,而不是在 EE 容器中。 我的 Maven 项目有com.google.dagger:dagger
和org.glassfish.jersey.containers:jersey-container-grizzly2-http
作为依赖项,但没有org.glassfish.jersey.inject:jersey-hk2
,因为我想替换 HK2用匕首。
资源类如下所示:
@Path("/example")
public final class ExampleResource {
private final Dependency dependency;
@Inject
public ExampleResource(final Dependency dependency) {
this.dependency = Objects.requireNonNull(dependency);
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Example getExample() {
return this.dependency.giveExample();
}
}
Dagger 组件可以定义如下:
@Component
public interface Application {
public ExampleResource exampleEndpoint();
public XyzResource xyzEndpoint();
// etc.
}
这样 main 方法看起来类似于:
public final class Main {
public static void main(final String[] args) {
final Application application = DaggerApplication.create();
final URI baseUri = UriBuilder.fromUri("http://0.0.0.0/").port(80).build();
final ResourceConfig resourceConfig = new ResourceConfig();
// how to initialize `resourceConfig` using `application`?
final HttpServer httpServer = GrizzlyHttpServerFactory
.createHttpServer(baseUri, resourceConfig, false);
try {
httpServer.start();
} catch (final IOException ex) {
...
}
}
}
立即运行应用程序会导致异常: IllegalStateException: InjectionManagerFactory not found.
似乎需要这个工厂的 Dagger 实现。
我的问题是:如何将 Dagger 与 Jersey 集成?
您不应该将其视为“如何将匕首与球衣融为一体”。 弄清楚如何设置 jersey,然后一旦弄清楚了,就可以担心使用匕首了。
这是(非常粗略地)我会怎么做。
创建您自己的 ResourceConfig class 实现。
@ApplicationPath("/service")
public class MyResourceConfig extends ResourceConfig {
@Inject
public MyResourceConfig(
@Nonnull final ExampleResource exampleResource) {
this.register(exampleResource);
}
}
然后创建一个模块来设置创建 HttpServer 所需的一切
@Module
public class MyServiceModule {
@Provides
@Singleton
@Named("applicationPort")
public Integer applicationPort() {
return 80;
}
@Provides
@Singleton
@Named("applicationBaseUri")
public URI baseUri(
@Named("applicationPort") @Nonnull final Integer applicationPort) {
return UriBuilder.fromUri("http://0.0.0.0/").port(applicationPort).build();
};
@Provides
@Singleton
public HttpServer httpServer(
@Named("applicationBaseUri") @Nonnull final URI applicationBaseUri,
@Nonnull final MyResourceConfig myResourceConfig) {
return GrizzlyHttpServerFactory
.createHttpServer(applicationBaseUri, myResourceConfig, false);
}
}
然后创建公开 HttpServer 的组件。 我通常喜欢制作尽可能少暴露的组件。 在这种情况下,您需要公开的只是 HttpServer。
@Singleton
@Component(modules = { MyServiceModule.class })
protected interface ServiceComponent {
HttpServer httpServer();
@Component.Builder
interface Builder {
// Bind any parameters here...
ServiceComponent build();
}
}
然后只需 go 并构建您的组件,并启动您的 HttpServer
public static void main(String[] args) {
final ServiceComponent component = DaggerServiceComponent.builder().build()
try {
component.httpServer().start();
} catch (Exception ex) {
// handle exception...
}
}
还有一件事要注意。 我个人从不使用 @Named("") 注释。 我更喜欢使用限定词。 因此,您创建了一个具有唯一值的 Qualifier 注释。 然后你可以注入类似的东西
@Provides
@Singleton
@MyUniqueQualifier
public String myUniqueQualifierProviderValue() {
return "something";
}
然后注射的时候
@Inject
public SomeClass(@MyUniqueQualifier @Nonnull final String myUniqueQualifiedValue)
如果您使用 @Named 注释,您将不会在编译时检查是否存在冲突或缺失值。 您会在运行时发现没有注入值,或者名称与其他名称冲突。 它很快就会变得凌乱。
您需要实现一个InjectionManagerFactory
,它将返回一个委托给Dagger的InjectionManager
,并通过在META-INF/services
一个条目将其注册为META-INF/services
,类似于hk2: https : //github.com/jersey/jersey /blob/master/inject/hk2/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory但引用了您自己的实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.