♨️

Springの@EventListenerをつかってイベントの発火を検知して処理を動かす

2023/07/22に公開

なにがうれしいか

  • イベントの発火に連動して動作させたい処理を、イベントを発火させるクラスから分離できる。
  • ドメインイベントを自然に記述できる(ドメインと関係が薄い部分を分離できる)
    • 「○○を変更したら通知したい」など

手順

登場人物として以下があります。順番に作っていきます。

  • イベントクラス
  • イベントを発火するクラス
  • イベントの発火を検知して動くクラス

Step1 イベントクラスを作る

ApplicationEventを継承したユーザー定義クラスを作成します。

サンプルコードではMyイベント型としていますが"社員の所属部署変更型"などの名称の方がイメージしやすいかもしれません。

package com.example.JavaTechnologySample.EventListener;  
  
import org.springframework.context.ApplicationEvent;  
  
public class Myイベント型 extends ApplicationEvent {  
	// 引数のsourceは発火したクラスのオブジェクト
	public Myイベント型(Object source) {  
		super(source);  
	}  
}

Step2 イベントを発火するクラスを作る

ApplicationEventPublisherを持つクラスを作成します。
ApplicationEventPublisher.publishEvent()を呼び出すことで発火します。

Step1でイベントクラスを"社員の所属部署変更型"とした場合は、イベントを発火するクラスは"社員の所属部署サービス型"の方がイメージしやすいかもしれません。

package com.example.JavaTechnologySample.EventListener;  
  
import org.springframework.context.ApplicationEventPublisher;  
import org.springframework.stereotype.Service;  
  
@Service  
public class Myサービス型 {  
	final ApplicationEventPublisher applicationEventPublisher;  
	  
	public Myサービス型(ApplicationEventPublisher applicationEventPublisher) {  
		this.applicationEventPublisher = applicationEventPublisher;  
	}  
	
	public Myイベント型 ほにゃららを更新する(){  

		// ここでほにゃららを更新したとする

		Myイベント型 myEvent = new Myイベント型(this);  
		applicationEventPublisher.publishEvent(myEvent);  
		
		return myEvent;  
	}  
}

Step3 イベントの発火を検知して動くクラスを作る

@EventListenerをつけたメソッドを作り、引数に検知したいイベント型を指定します。

また、@EventListenerはSpringの機能なため、このクラスはSpringのBeanとして登録されている必要があるので@Componentをつけます。

package com.example.JavaTechnologySample.EventListener;  
  
import org.springframework.context.event.EventListener;  
import org.springframework.stereotype.Component;  
  
@Component
public class MyListener{  
	@EventListener
	void 引数のイベントが発火すると動くメソッド(Myイベント型 event){  
		System.out.println("Myイベントに連動して@EventListenerの処理が動きました!");
	}  
}

まとめ

@EventListenerを使うことで、処理を分離することができました。

Myサービス型では"ほにゃららを更新する"というメソッドを作りましたが、このメソッドの中に"変更内容を関係者にメールで通知する"などの処理が書かれている場合、メソッド名とは乖離した処理が行われることになる問題を解決することができます。

とはいえ、イベントが発火したときに具体的にどの処理が動くのかを把握するためにはエディタの機能などを利用して、イベントの利用箇所を調べる必要があったりもします。

このように、使いこなしには慣れが必要な機能ですが、うまく使えば見通しがよい処理を書くことが出来るので開発効率や保守性を高めることができます。また、ドメインイベントを自然に記述することで、ビジネスロジックとイベントの関連性を明確にし、コードの理解や変更の際のリスクを低減することもできます。

しかし、@EventListenerを使用する際にはいくつか留意すべき点があります。例えば、イベントの発火順序や非同期処理など、実行順序に依存する場合には注意が必要です。また、過度に複雑なイベント処理のネットワークが形成されないように、イベントの適切な設計と利用を心掛けることも重要です。

@EventListenerでより良いプログラムを実現してください!

Happy coding!

参考

Discussion