Micronautのイベント発行とリスナーの使い方!アプリ内通信の基本をやさしく解説
生徒
「Micronautで、ある処理が終わったことを別のクラスに伝えたいときは、どう書けばいいんですか?」
先生
「そのような場面では、Micronautのイベント機能を使うと、クラス同士を直接つなげずに通知できます。」
生徒
「直接呼び出さない、というのが少しイメージできません。」
先生
「イベントを発行する側と、受け取る側を分けることで、柔軟で変更に強い設計になります。順番に見ていきましょう。」
1. Micronautにおけるイベント駆動の考え方
Micronautでは、DIコンテナを中心にアプリケーションが構成されています。 その中で、処理の完了や状態の変化を他のコンポーネントへ伝える方法として、 イベント発行とリスナーという仕組みが用意されています。
イベント駆動とは、ある出来事が発生したことを通知し、それを必要なクラスが受け取って処理する考え方です。 この方法を使うと、処理の呼び出し元と呼び出し先が直接依存しなくなります。 結果として、コードの見通しが良くなり、後から機能を追加しやすくなります。
2. イベント発行とリスナーの基本構造
Micronautのイベント機能は、大きく分けて三つの要素で構成されています。 一つ目はイベントクラス、二つ目はイベントを発行するクラス、 三つ目はイベントを受け取るリスナーです。
イベントクラスは、通知したい情報をまとめた単純なクラスです。 発行側は、このイベントをApplicationEventPublisherを通して送信します。 リスナーは、特定のイベントを受け取ると自動的に処理を実行します。
3. イベントクラスを作成する
まずは、通知したい内容を表すイベントクラスを作成します。 イベントクラスは特別な継承を必要とせず、通常のJavaクラスとして定義できます。 このシンプルさが、初心者にも扱いやすい理由です。
public class UserCreatedEvent {
private final String username;
public UserCreatedEvent(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
}
この例では、ユーザーが作成されたことを通知するイベントを定義しています。 イベントに含めたい情報をフィールドとして持たせることで、 リスナー側でその情報を利用できます。
4. イベントを発行する方法
次に、イベントを発行する側の実装です。 Micronautでは、ApplicationEventPublisherをDIで注入し、 publishEventメソッドを呼び出すだけでイベントを送信できます。
import io.micronaut.context.event.ApplicationEventPublisher;
import jakarta.inject.Singleton;
@Singleton
public class UserService {
private final ApplicationEventPublisher<UserCreatedEvent> eventPublisher;
public UserService(ApplicationEventPublisher<UserCreatedEvent> eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void createUser(String username) {
System.out.println("ユーザーを作成しました: " + username);
eventPublisher.publishEvent(new UserCreatedEvent(username));
}
}
このコードでは、ユーザー作成処理の後にイベントを発行しています。 UserServiceは、イベントを受け取る側の存在を一切意識していません。 これにより、後から処理を追加してもUserServiceを修正する必要がなくなります。
5. イベントリスナーを定義する
イベントを受け取るには、リスナーを定義します。 Micronautでは、ApplicationEventListenerインターフェースを実装する方法が基本です。 対象のイベント型を指定することで、自動的に呼び出されます。
import io.micronaut.context.event.ApplicationEventListener;
import jakarta.inject.Singleton;
@Singleton
public class UserCreatedListener implements ApplicationEventListener<UserCreatedEvent> {
@Override
public void onApplicationEvent(UserCreatedEvent event) {
System.out.println("イベントを受信しました: " + event.getUsername());
}
}
このリスナーは、UserCreatedEventが発行されると自動的に実行されます。 イベントの内容を受け取り、ログ出力や追加処理を行えます。 このように、処理を分離できる点がイベント設計の大きな利点です。
6. イベントを使うメリットと利用シーン
イベント発行とリスナーを使う最大のメリットは、疎結合な設計を実現できることです。 処理同士が直接依存しないため、変更や追加に強い構造になります。 特に、通知処理やログ記録、メール送信などに向いています。
Micronautのイベント機構はDIと自然に組み合わさっており、 アノテーションベースで簡潔に実装できます。 初心者のうちからイベントの考え方に慣れておくことで、 将来的に大規模なアプリケーションを設計する際にも役立ちます。