カテゴリ: Micronaut 更新日: 2026/04/04

Micronautの@Factoryとは?複雑なBean生成を管理するための方法を解説

Micronautの@Factoryとは?複雑なBean生成を管理するための方法を解説
Micronautの@Factoryとは?複雑なBean生成を管理するための方法を解説

先生と生徒の会話形式で理解しよう

生徒

「Micronautで@Factoryというアノテーションを見かけたんですが、これは何をするものなんですか?」

先生

「@Factoryは、少し複雑なBeanの生成処理をまとめて管理するための仕組みです」

生徒

「@Singletonや@Prototypeと何が違うんですか?」

先生

「それらはクラスそのものをBeanにしますが、@FactoryはBeanを作るためのクラスです」

生徒

「どういう場面で使うのか知りたいです」

先生

「では、DIの基本を振り返りながら、@Factoryの役割を見ていきましょう」

1. MicronautのDIとBean生成の基本

1. MicronautのDIとBean生成の基本
1. MicronautのDIとBean生成の基本

Micronautでは、DIによってオブジェクトの生成と管理をフレームワークが担当します。 開発者は、どのクラスをBeanとして使うかをアノテーションで指定するだけです。 これにより、newを直接書かずに、安全でテストしやすいコードが書けるようになります。

多くの場合は、@Singletonや@Prototypeをクラスに付けるだけで十分です。 しかし、生成時に条件分岐が必要だったり、外部設定を使った初期化が必要な場合もあります。 そのようなときに活躍するのが@Factoryです。

2. @Factoryとは何か

2. @Factoryとは何か
2. @Factoryとは何か

@Factoryは、Beanを生成するためのクラスを定義するアノテーションです。 @Factoryが付いたクラスの中で、Beanを返すメソッドを定義することで、 Micronautはその戻り値をDIコンテナに登録します。

つまり、@Factoryは「Beanそのもの」ではなく、 「Beanを作る責任を持ったクラス」と考えると分かりやすいです。 複雑な初期化処理を一か所にまとめられる点が大きな特徴です。

3. @Factoryの基本的な書き方

3. @Factoryの基本的な書き方
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が必要なのか

4. なぜ@Factoryが必要なのか
4. なぜ@Factoryが必要なのか

単純なクラスであれば、クラスに@Singletonを付けるだけで問題ありません。 しかし、生成時に設定値を組み合わせたり、 複数の条件によって生成方法を変えたい場合には、クラスに直接書くと複雑になります。

@Factoryを使えば、生成ロジックを専用クラスに切り出せます。 これにより、責務が分離され、コードの見通しが良くなります。 初心者でも、役割を意識しながら設計しやすくなる点がメリットです。

5. 複数のBeanを生成するFactory

5. 複数のBeanを生成する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とスコープの関係

6. @Factoryとスコープの関係
6. @Factoryとスコープの関係

@Factory自体にはスコープの意味はありません。 実際のスコープは、Beanを返すメソッドに付与されたアノテーションで決まります。

@Singletonを付ければ一つのインスタンスが共有され、 @Prototypeを付ければ呼び出されるたびに新しいインスタンスが生成されます。 この組み合わせにより、柔軟な設計が可能になります。

7. @Factoryを使う際の注意点

7. @Factoryを使う際の注意点
7. @Factoryを使う際の注意点

@Factoryは強力ですが、使いすぎると構成が分かりにくくなる場合があります。 単純なクラスまでFactoryで管理すると、かえって理解しづらくなることもあります。

まずは、複雑な生成処理が必要な場合に限定して使うのがおすすめです。 初心者のうちは、@Singletonと@Prototypeを基本にして、 必要になったタイミングで@Factoryを導入するとスムーズに理解できます。

まとめ

まとめ
まとめ

MicronautにおけるFactoryは、複雑なBean生成を整理し、アプリケーション全体の設計をより明確にするための重要な仕組みです。通常のDIでは、クラスにSingletonやPrototypeといったスコープを付与することで簡単にBeanを管理できますが、実務の開発ではそれだけでは対応しきれない場面が多く存在します。例えば、外部設定ファイルの値を読み込んで初期化したい場合や、環境によって生成するインスタンスを切り替えたい場合、あるいは複数の依存関係を組み合わせて一つのオブジェクトを構築する必要がある場合などです。こうしたケースにおいてFactoryを活用することで、生成ロジックを一箇所に集約でき、可読性と保守性を大きく向上させることができます。

また、Factoryを導入することで責務の分離が明確になります。クラス自身はビジネスロジックに専念し、生成に関する責任はFactoryに任せるという構造にすることで、コードの見通しが良くなります。これは大規模開発において特に重要なポイントであり、将来的な拡張やリファクタリングにも強い設計につながります。さらに、テストの観点でもFactoryは有効で、生成処理を差し替えることでモックの注入などが柔軟に行えるようになります。

一方で、Factoryは便利な反面、過度に使用すると逆に複雑さを招く可能性もあります。単純なクラスまでFactoryで管理してしまうと、どこでインスタンスが生成されているのか分かりにくくなり、学習コストも上がってしまいます。そのため、基本はSingletonやPrototypeを使い、どうしても生成処理が複雑になる場合にのみFactoryを採用するというバランスが重要です。初心者の方は、まずDIの基本をしっかり理解した上で、必要に応じてFactoryを導入する流れを意識すると良いでしょう。

サンプルプログラムで理解を深める

次のサンプルでは、設定値によって異なるサービスを生成するFactoryの例を示します。環境に応じてインスタンスを切り替えることで、柔軟な構成が実現できます。


import io.micronaut.context.annotation.Factory;
import jakarta.inject.Singleton;

@Factory
public class EnvironmentFactory {

    @Singleton
    public MessageService messageService() {
        String env = System.getProperty("env", "dev");

        if ("prod".equals(env)) {
            return new MessageService("本番環境");
        } else {
            return new MessageService("開発環境");
        }
    }
}

public class MessageService {

    private final String message;

    public MessageService(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

このようにFactoryを利用することで、条件分岐を含む生成ロジックを簡潔に記述でき、アプリケーション全体の構造が整理されます。特に設定値や環境変数と組み合わせることで、実務に即した柔軟な設計が可能になります。

先生と生徒の振り返り会話

生徒

Factoryを使う理由がだいぶ分かってきました。単純なクラスには不要だけど、複雑な生成処理にはとても便利なんですね。

先生

その通りです。特に設定値や条件分岐が絡むときに力を発揮します。生成処理を分離することで、コード全体が整理されます。

生徒

クラスに直接Singletonを付けるのと比べて、設計の自由度が上がる感じがしました。

先生

良い視点ですね。Factoryは柔軟性を高めるための仕組みです。ただし使いすぎには注意しましょう。

生徒

まずは基本のDIをしっかり理解して、必要な場面で使うようにします。

先生

それが一番良い進め方です。段階的に学ぶことで、実務でもしっかり活かせるようになります。

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

Micronautの@Factoryアノテーションとは何ですか?

@FactoryはMicronautでBeanを生成するための専用クラスを定義するアノテーションで、複雑な初期化や条件分岐をまとめて管理できます。
関連記事:
カテゴリの一覧へ
新着記事
New1
Quarkus
QuarkusのREST APIでJSONレスポンスを返す方法を完全解説!初心者向けJackson・JSON-B入門
New2
Quarkus
Quarkus拡張開発入門!GraalVMネイティブイメージ統合の仕組みを徹底解説
New3
Micronaut
Micronautの@Requiresとは?条件付きBeanの読み込み方法をやさしく解説【DIとアノテーション入門】
New4
Quarkus
Quarkusでマイクロサービス構成を作るプロジェクト設計を完全解説!初心者でも理解できる分割設計の考え方
人気記事
No.1
Java&Spring記事人気No1
Quarkus
Quarkus拡張開発を徹底解説!仕組みから自作エクステンションの作り方まで
No.2
Java&Spring記事人気No2
Java
Javaのコンパイルと実行の流れを解説!JVM・JDK・JREの違いも初心者向けに整理
No.3
Java&Spring記事人気No3
Quarkus
Quarkus入門!GitHub ActionsでCI/CDパイプラインを構築して自動ビルドを実現する方法
No.4
Java&Spring記事人気No4
Java
JavaのString検索方法を完全ガイド!contains・indexOf・startsWith・endsWithを徹底解説
No.5
Java&Spring記事人気No5
Java
JavaのString比較を徹底解説!equalsと==の違い、初心者が陥る罠とは?
No.6
Java&Spring記事人気No6
Java
Java Functionインタフェースの使い方を完全ガイド!map変換と処理チェーンを理解する
No.7
Java&Spring記事人気No7
Quarkus
Quarkus拡張開発入門!自作Extensionを作る基本ステップと仕組みを徹底解説
No.8
Java&Spring記事人気No8
Quarkus
Quarkus拡張開発をマスター!ビルドプロセスの仕組みと内部構造を徹底解説