tamuraです
DropwizardでGoogle Guiceを使ってDependency Injection(DI)を行いました。 DIを使った理由としてはデータベースコネクションを引き回したくなかったためです。
構成
リポジトリ
DAOを管理するクラスです。
クラス定義
Dropwizardでデータベースpart4 でやったように、abstractなDAOを用意します。
public abstract class Repository implements ransactional<Repository> {
@CreateSqlObject
public abstract SelectDAO createSelectDAO();
}
SelectDAO
などはこのabstractなDAOを継承して作ります。
使い方
DBIを使ってインスタンス化するところまでは一緒です。
public class Main extends Application<AppConfiguration> {
....
@Override
public void run(AppConfiguration configuration, Environment environment) throws Exception {
final DBIFactory factory = new DBIFactory();
final DBI jdbi = factory.build(environment, configuration.getDataSourceFactory(), "app");
final Repository repository = dbi.onDemand(Repository.class);
}
}
この後、GuiceのInjectorにこのインスタンスを登録します。
常にこのインスタンスが使われるように登録しておきます。
Injector injector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
// SomeServiceはSomeServiceImplが毎回新しいインスタンスが生成される
bind(SomeService.class).to(SomeServiceImpl.class);
// Repository.class は常に同じインスタンスが使われる
bind(Repository.class).toInstance(repository);
}
});
Resourceの定義
SomeResource
の実装の例です。
private
なフィールドに@Inject
をつけてもちゃんとインジェクションしてくれますが、
テストを行いやすいようにsetter
を用意しています。
@Path("/some")
@Produces(MediaType.APPLICATION_JSON)
public class SomeResource {
private SomeService someService;
@Inject
public void setSomeService(SomeService someService) {
this.someService = someService;
}
@GET
public String getSome() {
return someService.getSome();
}
}
Jerseyへの登録
environment.jersey().register(injector.getInstance(SomeResource.class));
上記のやり方で大丈夫です。
getInstance
でSomeResource
のインスタンスを取得できます。
特に何も紐付けしていない場合はSomeResource
がnew
されます。
Serviceの定義
まずはインターフェース。
public interface SomeService {
public String getSome();
}
続いて実装です。
ここでもsetter
を用意してテストを行いやすくしています。
public class SomeServiceImpl implements SomeService {
private Repository repository;
@Inject
public void setRepository(Repository repository) {
this.repository = repository;
}
@Override
public String getSome() {
SelectDAO dao = repository.createSelectDAO();
Optional<string> result = dao.selectSome();
if (result.isPresent()) {
return result.get();
}
else {
return "not found";
}
}
}
まとめ
Google Guiceを使うことで、データベースコネクションを引きずり回さなくてよくなりました。
1点注意が必要で、Guiceを使ってインスタンス化しないとインスタンスがインジェクションされません。 そのため「この条件の場合はこのロジッククラスをインスタンス化する」というようなロジックがあると、今回の方法は使えません。 (そういう作りはあまりないと思うのですが)