[英]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.