jersey
ジャージーとの依存性注射
サーチ…
JerseyのHK2を使用した基本依存性注入
Jersey(2)は依存性注入(DI)システムとしてHK2を使用しています。他の注入システムも使用できますが、そのインフラストラクチャはHK2で構築されており、アプリケーション内でも使用できます。
Jerseyを使って単純な依存関係注入を設定するには、ほんの数行のコードが必要です。たとえば、リソースに注入したいサービスがあるとします。
public class GreetingService {
public String getGreeting(String name) {
return "Hello " + name + "!";
}
}
そして、私たちはこのサービスをJerseyのリソースに注入したい
@Path("greeting")
public class GreetingResource {
@Inject
public GreetingService greetingService;
@GET
public String get(@QueryParam("name") String name) {
return this.greetingService.getGreeting(name);
}
}
注射が機能するためには、簡単な構成が必要です
@ApplicationPath("/api")
public class AppConfig extends ResourceConfig {
public AppConfig() {
register(GreetingResource.class);
register(new AbstractBinder() {
@Override
protected void configure() {
bindAsContract(GreetingService.class);
}
});
}
}
ここでは、 GreetingService
をインジェクションシステムにバインドして、同じクラスによってインジェクション可能なものとしてアドバタイズするとします。最後の声明が意味することは、 GreetingService
としてしか注入できないということです。他のどのクラスでも(おそらくは明らかに)注入できません。後で見るように、これを変更することは可能です。
それでおしまい。それはあなたが必要なすべてです。このResourceConfig
設定に慣れていない場合は(おそらくweb.xmlを使用しています)、SO DocsのJerseyのJAX-RS設定トピックを参照してください。
注:上記の注入は、サービスがリソースのフィールドに注入されるフィールドインジェクションです。別のタイプの注入はコンストラクタ注入であり、サービスはコンストラクタに注入されます
private final GreetingService greetingService;
@Inject
public GreetingResource(GreetingService greetingService) {
this.greetingService = greetingService;
}
これはおそらく、フィールドインジェクションとは対照的に、ユニットテストを容易にするための好ましい方法です。コンストラクター注入には、別の構成は必要ありません。
今度は、クラスの代わりに、 GreetingService
がインターフェイスであり、我々はその実装を持っています(これは非常に一般的です)。これを設定するには、上記のconfigure
メソッドで次の構文を使用します
@Override
protected void configure() {
bind(NiceGreetingService.class).to(GreetingService.class);
}
これは「 NiceGreetingService
バインドしてGreetingService
として広告する」と読みます。つまり、私たちはNiceGreetingService
なくGreetingService
として契約を宣伝しているので、上記のGreetingResource
で全く同じコードを使用できます。実際の実装は、注入するとNiceGreetingService
ます。
スコープはどうですか?注入フレームワークで作業したことがあるならば、サービスの寿命を決定するスコープの概念に着目することになります。あなたは、リクエストが終わってもサービスが生きている「リクエストスコープ」について聞いたことがあります。または、サービスのインスタンスが1つしかない「シングルトンスコープ」。これらのスコープは、次の構文を使用しても構成できます。
@Override
protected void configure() {
bind(NiceGreetingService.class)
.to(GreetingService.class)
.in(RequestScoped.class);
}
デフォルトのスコープはPerLookup
です。 PerLookup
、このサービスが要求されるたびに、新しいサービスが作成されます。上記の例では、 RequestScoped
を使用して、単一の要求に対して新しいサービスが作成されます。これはPerLookup
と同じかもしれませんが、私たちが注入しようとしている場所の数によって異なります。私たちはそれをフィルタとリソースに注入しようとしているかもしれません。これがPerLookup
場合は、リクエストごとに2つのインスタンスが作成されます。この場合、私たちは1つだけを必要とします。
使用可能な他の2つのスコープは、 Singleton
(インスタンスが1つだけ作成されます)とImmediate
( Singleton
ような)ですが、起動時に作成されます( Singleton
では最初の要求まで作成されません)。
クラスをバインドするだけでなく、インスタンスを使用することもできます。これにより、デフォルトシングルトンが得られるので、 in
構文を使用する必要はありません。
@Override
protected void configure() {
bind(new NiceGreetingService())
.to(GreetingService.class);
}
複雑な作成ロジックがある場合や、サービスのリクエストコンテキスト情報が必要な場合はどうなりますか?この場合、 Factory
があります。私たちがジャージーのリソースに注入できるほとんどのものは、 Factory
も注入することができます。たとえば、取る
public class GreetingServiceFactory implements Factory<GreetingService> {
@Context
UriInfo uriInfo;
@Override
public GreetingService provide() {
return new GreetingService(
uriInfo.getQueryParameters().getFirst("name"));
}
@Override
public void dispose(GreetingService service) {
/* noop */
}
}
ここでは、 UriInfo
からリクエスト情報を取得するファクトリがあります。この場合はクエリパラメータであり、そこからGreetingService
を作成します。これを設定するには、次の構文を使用します
@Override
protected void configure() {
bindFactory(GreetingServiceFactory.class)
.to(GreetingService.class)
.in(RequestScoped.class);
}
それでおしまい。これらは単なる基本です。 HKとジャージーにはもっとたくさんのことがあります。