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

Micronautの@Prototypeとは?新しいインスタンスを生成するスコープの基本

Micronautの@Prototypeとは?新しいインスタンスを生成するスコープの基本
Micronautの@Prototypeとは?新しいインスタンスを生成するスコープの基本

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

生徒

「Micronautで@Prototypeって書かれているクラスを見たんですが、@Singletonとは何が違うんですか?」

先生

「@Prototypeは、依存性注入されるたびに新しいインスタンスを生成するスコープです」

生徒

「毎回新しく作られるんですか?」

先生

「そうです。同じクラスでも、注入されるたびに別のオブジェクトになります」

生徒

「どういう場面で使い分けるのかが知りたいです」

先生

「では、@Prototypeの基本から順番に説明していきましょう」

1. Micronautにおけるスコープの基本

1. Micronautにおけるスコープの基本
1. Micronautにおけるスコープの基本

Micronautでは、DIによってオブジェクトの生成と管理をフレームワークに任せます。 その際に重要になるのがスコープという概念です。 スコープは、オブジェクトがいつ作られ、どの範囲で使われるかを決める仕組みです。

初心者が最初に触れるのは@Singletonですが、それとは対照的な存在が@Prototypeです。 この二つを理解すると、MicronautのDI設計が一気に分かりやすくなります。

2. @Prototypeとは何か

2. @Prototypeとは何か
2. @Prototypeとは何か

@Prototypeは、依存性注入されるたびに新しいインスタンスを生成するスコープです。 同じクラスであっても、使われる場所ごとに別々のオブジェクトが作られます。

そのため、状態を持つクラスや、一時的な処理を担当するクラスに向いています。 @Singletonのように使い回されることがないため、内部状態が他に影響する心配がありません。

3. @Prototypeの基本的な使い方

3. @Prototypeの基本的な使い方
3. @Prototypeの基本的な使い方

@Prototypeはクラスに付与するだけで利用できます。 特別な設定は不要で、Micronautが自動的に管理します。


import jakarta.inject.Prototype;

@Prototype
public class TaskProcessor {

    private int counter = 0;

    public int process() {
        counter++;
        return counter;
    }
}

このクラスは、注入されるたびに新しいインスタンスが生成されます。 counterの値も、それぞれ独立して管理されます。

4. @Prototypeが新しいインスタンスを生成する仕組み

4. @Prototypeが新しいインスタンスを生成する仕組み
4. @Prototypeが新しいインスタンスを生成する仕組み

@Prototypeが付いたクラスは、DIコンテナにキャッシュされません。 そのため、必要になるたびにインスタンスが作成されます。

次の例では、同じクラスを二回注入した場合でも、別のオブジェクトとして扱われます。


import jakarta.inject.Singleton;

@Singleton
public class TaskRunner {

    private final TaskProcessor taskProcessor1;
    private final TaskProcessor taskProcessor2;

    public TaskRunner(TaskProcessor taskProcessor1,
                      TaskProcessor taskProcessor2) {
        this.taskProcessor1 = taskProcessor1;
        this.taskProcessor2 = taskProcessor2;
    }

    public void run() {
        System.out.println(taskProcessor1.process());
        System.out.println(taskProcessor2.process());
    }
}

1
1

出力結果からも分かるように、それぞれのTaskProcessorは別のインスタンスです。 これが@Prototypeの最大の特徴です。

5. @Singletonとの違いを理解する

5. @Singletonとの違いを理解する
5. @Singletonとの違いを理解する

@Singletonはアプリケーション全体で一つのインスタンスを共有します。 一方で@Prototypeは、使われるたびに新しいインスタンスを作ります。

共通処理やサービスクラスは@Singleton、 一時的な処理や状態を持つクラスは@Prototype、 というように役割で使い分けるのが基本です。 この判断ができるようになると、Micronautの設計が一段と理解しやすくなります。

6. @Prototypeが向いている具体的な場面

6. @Prototypeが向いている具体的な場面
6. @Prototypeが向いている具体的な場面

@Prototypeは、リクエストごとに異なる処理を行うクラスや、 計算途中の状態を保持するクラスに向いています。 また、短時間しか使わないオブジェクトにも適しています。

初心者のうちは、状態を持つクラスには@Prototypeを使う、 状態を持たないクラスには@Singletonを使う、 というルールを意識すると混乱しにくくなります。

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

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

@Prototypeは便利ですが、インスタンス生成回数が増える点には注意が必要です。 大量に生成されると、パフォーマンスに影響する場合もあります。

そのため、本当に新しいインスタンスが必要かを考えた上で使うことが大切です。 MicronautのDIは高速ですが、設計の意図を明確にすることが重要です。

まとめ

まとめ
まとめ

MicronautとDIスコープの理解を深める総まとめ

Micronautにおける依存性注入の設計を理解するうえで、スコープという考え方は非常に重要なポイントとなります。 特に@Prototypeは、オブジェクトのライフサイクルを柔軟に制御するために欠かせない仕組みであり、アプリケーションの設計品質に大きく関わってきます。 本記事では、Micronaut DIの基本から、@Prototypeの特徴、@Singletonとの違い、実際のコード例を通して、その動作や使いどころを丁寧に解説してきました。

まず理解しておきたいのは、MicronautのDIは単なるオブジェクト生成の仕組みではなく、アプリケーション全体の構造を整理するための設計思想でもあるという点です。 その中でスコープは、オブジェクトがどのタイミングで生成され、どの範囲で共有されるのかを決定する重要な要素です。 @Prototypeは、依存性注入されるたびに新しいインスタンスを生成するという特徴を持ち、状態を持つ処理や一時的なロジックに適したスコープです。

例えば、処理の途中で値を保持するようなクラスや、毎回独立した状態で実行したい処理では、@Singletonではなく@Prototypeを選択することで、安全かつ直感的な設計が可能になります。 @Singletonの場合、インスタンスが共有されるため、意図しない状態の共有が発生するリスクがありますが、@Prototypeではその心配がありません。

サンプルコードで振り返るPrototypeの特徴


import jakarta.inject.Prototype;

@Prototype
public class CounterService {

    private int count = 0;

    public int increment() {
        count++;
        return count;
    }
}

上記のコードでは、CounterServiceは呼び出されるたびに新しいインスタンスが生成されるため、それぞれのcountは独立した値として管理されます。 つまり、同じクラスであっても、利用箇所ごとに全く別のオブジェクトとして扱われることになります。


import jakarta.inject.Singleton;

@Singleton
public class CounterRunner {

    private final CounterService service1;
    private final CounterService service2;

    public CounterRunner(CounterService service1, CounterService service2) {
        this.service1 = service1;
        this.service2 = service2;
    }

    public void run() {
        System.out.println(service1.increment());
        System.out.println(service2.increment());
    }
}

1
1

実行結果からも分かる通り、service1とservice2はそれぞれ別のインスタンスであり、同じ処理を行っても状態は共有されていません。 この動作こそが、@Prototypeの最大の特徴であり、設計上の大きなメリットです。

実務で役立つ使い分けのポイント

実際の開発では、すべてを@Prototypeにするのではなく、用途に応じて適切にスコープを使い分けることが重要です。 一般的な指針としては、共通処理や再利用されるサービスには@Singletonを使用し、状態を持つ処理や一時的な計算処理には@Prototypeを使用します。 この判断ができるようになると、コードの可読性や保守性が大きく向上します。

また、@Prototypeはインスタンス生成の回数が増えるため、パフォーマンスへの影響も考慮する必要があります。 Micronautは高速なDIコンテナを提供していますが、それでも不要なインスタンス生成は避けるべきです。 設計段階で本当に新しいインスタンスが必要かを見極めることが、良いアプリケーションを作るための鍵となります。

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

生徒

Micronautの@Prototypeについて理解できました。毎回新しいインスタンスが作られるというのが大きなポイントなんですね。

先生

その通りです。特に状態を持つ処理では、@Prototypeを使うことで安全に設計できます。

生徒

@Singletonとの違いもはっきりしました。共有するかしないかで選ぶという考え方ですね。

先生

はい。設計の意図を明確にすることが重要です。どのスコープを使うかで、アプリケーションの振る舞いが大きく変わります。

生徒

インスタンス生成のコストについても意識しないといけないですね。

先生

その視点はとても大切です。便利だからといって乱用せず、必要な場面で適切に使うことがプロの設計です。

生徒

今回の内容でMicronautのDI設計の考え方がかなり理解できました。

先生

良い理解です。この調子でスコープを意識した設計を続けていけば、より実践的な開発力が身についていきます。

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

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

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

Micronautで@Prototypeと@Singletonの違いは何ですか?

@Prototypeは注入されるたびに新しいインスタンスを生成します。一方で@Singletonはアプリケーション全体で1つのインスタンスを共有します。用途によって使い分けることが重要です。
関連記事:
カテゴリの一覧へ
新着記事
New1
Java
JavaのStringBufferクラスを徹底解説!スレッド安全な文字列操作の仕組みと使い分け
New2
Micronaut
Micronautで非同期HTTP処理を行う方法!リアクティブ対応の基礎知識
New3
Micronaut
Micronautの@Prototypeとは?新しいインスタンスを生成するスコープの基本
New4
Quarkus
QuarkusのCDIスコープを完全理解!@ApplicationScopedと@RequestScopedを初心者向けに徹底解説
人気記事
No.1
Java&Spring記事人気No1
Quarkus
Quarkus入門!GitHub ActionsでCI/CDパイプラインを構築して自動ビルドを実現する方法
No.2
Java&Spring記事人気No2
Java
Javaのコンパイルと実行の流れを解説!JVM・JDK・JREの違いも初心者向けに整理
No.3
Java&Spring記事人気No3
Micronaut
Micronautのルーティング設定ガイド!プレフィックス付与とAPIバージョニングの基本
No.4
Java&Spring記事人気No4
Java
Java Optional ifPresentの使い方を徹底解説!nullチェックをスマートに省略する方法
No.5
Java&Spring記事人気No5
Micronaut
Micronautのフィルタ徹底解説!HTTPリクエスト共通処理をスマートに追加する方法
No.6
Java&Spring記事人気No6
Quarkus
QuarkusのCI/CD入門!GitHub Actionsで自動デプロイを実現する方法
No.7
Java&Spring記事人気No7
Java
Java Functionインタフェースの使い方を完全ガイド!map変換と処理チェーンを理解する
No.8
Java&Spring記事人気No8
Java
JavaのString比較を徹底解説!equalsと==の違い、初心者が陥る罠とは?