Micronautの@Factoryとは?複雑なBean生成を管理するための方法を解説
生徒
「Micronautで@Factoryというアノテーションを見かけたんですが、これは何をするものなんですか?」
先生
「@Factoryは、少し複雑なBeanの生成処理をまとめて管理するための仕組みです」
生徒
「@Singletonや@Prototypeと何が違うんですか?」
先生
「それらはクラスそのものをBeanにしますが、@FactoryはBeanを作るためのクラスです」
生徒
「どういう場面で使うのか知りたいです」
先生
「では、DIの基本を振り返りながら、@Factoryの役割を見ていきましょう」
1. MicronautのDIとBean生成の基本
Micronautでは、DIによってオブジェクトの生成と管理をフレームワークが担当します。 開発者は、どのクラスをBeanとして使うかをアノテーションで指定するだけです。 これにより、newを直接書かずに、安全でテストしやすいコードが書けるようになります。
多くの場合は、@Singletonや@Prototypeをクラスに付けるだけで十分です。 しかし、生成時に条件分岐が必要だったり、外部設定を使った初期化が必要な場合もあります。 そのようなときに活躍するのが@Factoryです。
2. @Factoryとは何か
@Factoryは、Beanを生成するためのクラスを定義するアノテーションです。 @Factoryが付いたクラスの中で、Beanを返すメソッドを定義することで、 Micronautはその戻り値をDIコンテナに登録します。
つまり、@Factoryは「Beanそのもの」ではなく、 「Beanを作る責任を持ったクラス」と考えると分かりやすいです。 複雑な初期化処理を一か所にまとめられる点が大きな特徴です。
3. @Factoryの基本的な書き方
@Factoryはクラスに付与し、その中でBeanを返すメソッドを定義します。 メソッドには@Singletonや@Prototypeなどのスコープを指定します。
import io.micronaut.context.annotation.Factory;
import jakarta.inject.Singleton;
@Factory
public class ServiceFactory {
@Singleton
public SampleService sampleService() {
return new SampleService("default");
}
}
public class SampleService {
private final String name;
public SampleService(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
この例では、SampleServiceは直接Beanとして定義されていません。 代わりに、Factoryクラスのメソッドを通して生成されます。 これにより、生成ロジックを柔軟に制御できます。
4. なぜ@Factoryが必要なのか
単純なクラスであれば、クラスに@Singletonを付けるだけで問題ありません。 しかし、生成時に設定値を組み合わせたり、 複数の条件によって生成方法を変えたい場合には、クラスに直接書くと複雑になります。
@Factoryを使えば、生成ロジックを専用クラスに切り出せます。 これにより、責務が分離され、コードの見通しが良くなります。 初心者でも、役割を意識しながら設計しやすくなる点がメリットです。
5. 複数のBeanを生成するFactory
一つの@Factoryクラスの中で、複数のBeanを定義することも可能です。 関連するBeanをまとめて管理できるため、構成が分かりやすくなります。
import io.micronaut.context.annotation.Factory;
import jakarta.inject.Singleton;
@Factory
public class ConfigFactory {
@Singleton
public ConfigService configService() {
return new ConfigService("prod");
}
@Singleton
public HelperService helperService() {
return new HelperService();
}
}
このように、設定や補助的なサービスをまとめて生成することで、 アプリケーション全体の構成が整理されます。
6. @Factoryとスコープの関係
@Factory自体にはスコープの意味はありません。 実際のスコープは、Beanを返すメソッドに付与されたアノテーションで決まります。
@Singletonを付ければ一つのインスタンスが共有され、 @Prototypeを付ければ呼び出されるたびに新しいインスタンスが生成されます。 この組み合わせにより、柔軟な設計が可能になります。
7. @Factoryを使う際の注意点
@Factoryは強力ですが、使いすぎると構成が分かりにくくなる場合があります。 単純なクラスまでFactoryで管理すると、かえって理解しづらくなることもあります。
まずは、複雑な生成処理が必要な場合に限定して使うのがおすすめです。 初心者のうちは、@Singletonと@Prototypeを基本にして、 必要になったタイミングで@Factoryを導入するとスムーズに理解できます。