カテゴリ: 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のフォーム認証を基礎から解説!初心者向けセキュリティ入門ガイド
New2
Micronaut
MicronautプロジェクトをGradleで管理する基礎!build.gradleの役割を解説
New3
Micronaut
LinuxでMicronautをセットアップする方法!パッケージ管理とGradle連携
New4
Java
Javaのswitch文を徹底解説!case・defaultの書き方と実例まとめ
人気記事
No.1
Java&Spring記事人気No1
Quarkus
Quarkusプロジェクト構成の基本を完全解説!初心者でも迷わない「どこに何を書くか」ガイド
No.2
Java&Spring記事人気No2
Quarkus
QuarkusとMicronautとHelidonを徹底比較!軽量Javaフレームワークの違いを初心者向けに解説
No.3
Java&Spring記事人気No3
Quarkus
Quarkusのセキュリティ基礎を初心者でもわかるように解説!
No.4
Java&Spring記事人気No4
Micronaut
MicronautとSpring Bootの違いとは?アーキテクチャ比較で速さの秘密を理解する
No.5
Java&Spring記事人気No5
Quarkus
Quarkusの開発環境構築で躓きやすいポイントを完全解説!初心者でも安心して始めるためのチェックガイド
No.6
Java&Spring記事人気No6
Quarkus
Quarkusでマイクロサービス開発が加速する理由を徹底解説!Java初心者でも分かるクラウドネイティブ
No.7
Java&Spring記事人気No7
Micronaut
MicronautのAOPが高速な理由とは?コンパイル時AOPの仕組みを初心者向けに徹底解説
No.8
Java&Spring記事人気No8
Micronaut
Micronautのアプリケーション起動が速い理由を初心者向けに解説