カテゴリ: Micronaut 更新日: 2026/01/31

Micronautでインタフェース実装Beanを切り替える方法!複数実装を安全に管理するDI入門

Micronautでインタフェースを実装するBeanを切り替える方法!複数実装の管理
Micronautでインタフェースを実装するBeanを切り替える方法!複数実装の管理

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

生徒

「Micronautでインタフェースを作ったら、実装クラスが複数あってエラーが出ました……」

先生

「DIでは、どの実装を使うか指定しないと、Micronautが判断できなくなることがあります」

生徒

「Springみたいに設定で切り替えたりできるんですか?」

先生

「できます。Micronautではアノテーションを使って、複数実装の管理や切り替えができます」

生徒

「初心者でも混乱しない方法を知りたいです」

先生

「では、インタフェースと複数Beanの基本から順番に整理していきましょう」

1. Micronautとインタフェース設計の基本

1. Micronautとインタフェース設計の基本
1. Micronautとインタフェース設計の基本

MicronautはDIを前提としたJavaフレームワークであり、インタフェースを使った設計と非常に相性が良いです。 インタフェースを用いることで、実装を差し替えやすくなり、テストや機能追加が簡単になります。 その一方で、同じインタフェースを実装したクラスが複数存在すると、DI時にどれを使うか決められずエラーになります。

初心者が遭遇しやすいのが、インタフェースを定義し、実装クラスを二つ以上作った瞬間に発生する依存性解決エラーです。 Micronautでは、これを明示的に制御する仕組みが用意されています。

2. インタフェースと複数実装を定義する

2. インタフェースと複数実装を定義する
2. インタフェースと複数実装を定義する

まずは、基本となるインタフェースと、その実装クラスを作成します。 ここでは通知処理を例にして、コンソール出力とログ出力の二つの実装を用意します。


public interface NotificationService {
    void notifyMessage(String message);
}

import jakarta.inject.Singleton;

@Singleton
public class ConsoleNotificationService implements NotificationService {

    @Override
    public void notifyMessage(String message) {
        System.out.println("Console通知: " + message);
    }
}

import jakarta.inject.Singleton;

@Singleton
public class LogNotificationService implements NotificationService {

    @Override
    public void notifyMessage(String message) {
        System.out.println("Log通知: " + message);
    }
}

この状態でNotificationServiceをDIしようとすると、Micronautはどちらを使うべきか判断できません。 そのため、複数実装を管理する仕組みが必要になります。

3. Primaryを使ってデフォルト実装を決める

3. Primaryを使ってデフォルト実装を決める
3. Primaryを使ってデフォルト実装を決める

最も簡単な方法がPrimaryアノテーションを使う方法です。 Primaryを付与したBeanは、複数候補がある場合のデフォルトとして選ばれます。 初心者にとって理解しやすく、設定量も少ないのが特徴です。


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

@Singleton
@Primary
public class ConsoleNotificationService implements NotificationService {

    @Override
    public void notifyMessage(String message) {
        System.out.println("Console通知: " + message);
    }
}

この指定により、NotificationServiceを注入した場合はConsoleNotificationServiceが使われます。 まず一つの実装を基準にしたい場合に有効な方法です。

4. Qualifierを使って明示的に切り替える

4. Qualifierを使って明示的に切り替える
4. Qualifierを使って明示的に切り替える

実装を用途ごとに切り替えたい場合は、Qualifierを使う方法が適しています。 Qualifierは、Beanに名前や識別子を付けて区別する仕組みです。 MicronautではNamedアノテーションがよく使われます。


import jakarta.inject.Singleton;
import jakarta.inject.Named;

@Singleton
@Named("console")
public class ConsoleNotificationService implements NotificationService {

    @Override
    public void notifyMessage(String message) {
        System.out.println("Console通知: " + message);
    }
}

import jakarta.inject.Singleton;
import jakarta.inject.Named;

@Singleton
@Named("log")
public class LogNotificationService implements NotificationService {

    @Override
    public void notifyMessage(String message) {
        System.out.println("Log通知: " + message);
    }
}

import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.inject.Singleton;

@Singleton
public class NotificationClient {

    private final NotificationService notificationService;

    @Inject
    public NotificationClient(@Named("console") NotificationService notificationService) {
        this.notificationService = notificationService;
    }

    public void execute() {
        notificationService.notifyMessage("処理が完了しました");
    }
}

このようにすることで、使用する実装をコード上で明示できます。 複数実装を安全に使い分けたい場合に非常に便利です。

5. 複数実装をリストとして受け取る方法

5. 複数実装をリストとして受け取る方法
5. 複数実装をリストとして受け取る方法

Micronautでは、同じインタフェースを実装したBeanをすべてまとめて受け取ることも可能です。 これにより、処理をループで実行したり、条件によって動的に選択できます。


import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.util.List;

@Singleton
public class BatchNotificationService {

    private final List<NotificationService> services;

    @Inject
    public BatchNotificationService(List<NotificationService> services) {
        this.services = services;
    }

    public void notifyAllServices(String message) {
        for (NotificationService service : services) {
            service.notifyMessage(message);
        }
    }
}

この方法は拡張性が高く、新しい実装を追加してもコード修正が最小限で済みます。 プラグイン的な設計を行いたい場合にも役立ちます。

6. 初心者が混乱しやすいポイントと考え方

6. 初心者が混乱しやすいポイントと考え方
6. 初心者が混乱しやすいポイントと考え方

初心者が混乱しやすいのは、インタフェースを作っただけで自動的に切り替わると誤解してしまう点です。 Micronautは明示的な指定を重視するため、複数実装がある場合は必ず選択ルールを与える必要があります。

まずはPrimaryで一つに決める、次にQualifierで切り替える、最後に一覧取得という順番で理解すると、 MicronautのDIとインタフェース設計が自然に身につきます。

関連記事:
カテゴリの一覧へ
新着記事
New1
Quarkus
QuarkusとGraalVMの進化を徹底解説!Javaネイティブイメージが切り拓く次世代開発の将来展望
New2
Micronaut
Micronaut + IntelliJ のプラグイン活用術!自動補完・テンプレート便利機能紹介
New3
Quarkus
QuarkusとGitHub Codespacesでクラウド開発を始める方法を完全解説!初心者でも迷わない開発環境構築ガイド
New4
Java
Java LocalTimeの使いどころ|時刻だけを扱う設計パターンを完全マスター
人気記事
No.1
Java&Spring記事人気No1
Quarkus
Quarkus拡張開発を徹底解説!仕組みから自作エクステンションの作り方まで
No.2
Java&Spring記事人気No2
Java
Javaの配列とは?基本の使い方・宣言・初期化を初心者向けにわかりやすく解説
No.3
Java&Spring記事人気No3
Java
Java ArrayListの使い方完全ガイド|追加・削除・取得・検索の基本操作
No.4
Java&Spring記事人気No4
Micronaut
MicronautのHTTPサーバー性能を最大化!初心者でもできるパフォーマンスチューニング
No.5
Java&Spring記事人気No5
Java
Javaの型変換(キャスト)を徹底解説!暗黙的・明示的変換の違いを整理
No.6
Java&Spring記事人気No6
Java
Javaの配列検索を完全攻略!値の探し方や多次元配列の条件一致を解説
No.7
Java&Spring記事人気No7
Quarkus
Quarkus拡張開発をマスター!ビルドプロセスの仕組みと内部構造を徹底解説
No.8
Java&Spring記事人気No8
Java
Javaのコンパイルと実行の流れを解説!JVM・JDK・JREの違いも初心者向けに整理