2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ratpack入門 (7) - Guice & Spring

Last updated at Posted at 2018-02-09

Ratpack入門シリーズ

  1. Ratpack入門 (1) - Ratpackとは
  2. Ratpack入門 (2) - アーキテクチャー
  3. Ratpack入門 (3) - hello world 詳解
  4. Ratpack入門 (4) - ルーティング & 静的コンテンツ
  5. Ratpack入門 (5) - Json & Registry
  6. Ratpack入門 (6) - Promise
  7. Ratpack入門 (7) - Guice & Spring
  8. Ratpack入門 (8) - セッション
  9. Ratpack入門 (9) - Thymeleaf

DIコンテナー

Ratpackは、以前書いたように様々な部品をRegistryクラスに登録することで、モジュラーなアーキテクチャーを実現しています。これ自体は理想的かつフレキシブルなものであると言えますが、大規模開発にはやはり本格的なDIコンテナーが必要になってくると思います。RatpackはGoogle GuiceまたはSpringのDI機能を、Registryとして使用することができます。

Guice

ratpack.guice.Guiceクラスから、Registryを作成できます。名前がcom.google.inject.Guiceとかぶっているので注意が必要です。InjectorクラスからRegistryを作成する例です。

Injector injector = Guice.createInjector( new CustomModule() );
Registry registry = ratpack.guice.Guice.registry( injector );

モジュール作成をRatpack内部のAPIのみから行うこともできます。型がFunction<Registry, Registry>といびつですが、直接RatpackServerSpec.registry()に渡すことができます。

Function<Registry, Registry> registry = ratpack.guice.Guice.registry( bindings -> {
    bindings.module( CustomModule.class );
} );

モジュールの追加は順番に影響されることに留意する必要があります。後から追加されるモジュールに、内容が上書きされます。

使い方は普通のRegistryと同様です。Guiceのインジェクターに登録されたクラスを、RegistryのAPIから取得することができます。ハンドラーなどをクラス名で指定すると、コンテナーから取得してくれます。インスタンスの管理はGuiceによって行われているので、普通のGuiceのコードと同じく、依存関係を@Injectで指定することができます。

public final class CustomHandler implements Handler {

    private Database database;

    @Inject
    public CustomHandler( Database database ) {
        this.database = database;
    }

    @Override
    public void handle( Context ctx ) throws Exception {
        ctx.render( "CustomHandler: " + database.find() );
    }
}
Action<Chain> handlers = chain -> {
    chain.all( CustomHandler.class );
};

InjectionHandler

RatpackはGuiceのボイラープレートを減らすため、InjectionHandlerクラスを提供しています。

public static final class CustomInjectionHandler extends InjectionHandler {
    public void handle( Context context, Database database ) {
        context.render( "CustomInjectionHandler: " + database.find() );
    }
}

InjectionHandlerを継承したクラスは、handlerという名前で、第一引数にContextを持つ関数を一つだけ実装します。Contextに続いて、注入したい依存関係を引数として記述します。
内部的にはハンドラーの呼び出しに対してリフレクションで当該メソッドに処理を委譲する形をとっています。
パフォーマンスやIDEの支援を考えると、個人的にはあまり使用しないほうが良いと思います。

Spring

ratpack.spring.Spring.spring()メソッドで、SpringのDIコンテナーからRegistryを作成できます。

Registry registry = Spring.spring( Application.class );

引数に指定するクラスは、@SpringBootApplicationアノテーションのついたクラスです。通常のSpringアプリケーションで使うのと同じで、クラスパスからコンポーネントが検索され、それらのクラスはRegistryから取得できます。

@Service
public class CustomRenderer implements Handler {

    private final CustomRepository repository;

    @Autowired
    public CustomRenderer( CustomRepository repository ) {
        this.repository = repository;
    }

    @Override
    public void handle( Context ctx ) throws Exception {
        ctx.render( "Hello from Spring Boot!" );
    }
}
@Repository
public static class CustomRepository {
    public String find() {
        return "This is the mock database.";
    }
}
Action<Chain> handlers = chain -> {
    chain.all( CustomRenderer.class );
};

まとめ

Javaエコシステムでは、DIコンテナーの使用はほぼ必須と言っていいほどだと思います。Ratpackは特によくつかわれるGuiceとSpringという二つのDIコンテナーに対するサポートを提供しています。また、GuiceはRatpackの各拡張モジュールの統合にも利用されます。

RatpackとGuiceは密接に統合されており、また、DI自体もアプリケーションを疎結合にする強力な手段です。積極的に利用することをお勧めします。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?