しゃべぶろ

気になった技術の備忘録を残します。

【Spring Framework】ApplicationEventについて

概要

Springでイベント通知をしたい場合は、ApplicationEventを発行してあげれば良い。
発行するにはApplicationEventPublisherそして、ApplicationListenerを使ってイベントを受信する。
これらを使えば、コンポーネント間の独立性を高める事が出来る。

ApplicationEvent

ApplicationEventは抽象クラスとなっていので、利用用途毎にサブラクスを作成する必要がある。

public class SampleEvent extends ApplicationEvent{

    private final String msg;

    public SampleEvent(Object source, String msg) {
        super(source);
        this.msg = msg;
    }

    public String getMsg () {
        return msg;
    }
}

ApplicationEvent自体は大して重要ではない。
重要なのは、ApplicationEventPublisherApplicationListener

ApplicationEventPublisher

イベントを発行する事が出来るインターフェイスである。

@Component
public class SamplePublisher {

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void sendMessage(String msg) {
        applicationEventPublisher.publishEvent(new SampleEvent(this, msg));
    }

}

publishEvent()はAbstractApplicationContext内で実装されている。
実装を見ると発行されたEventはAbstractApplicationContext内に保持または、
ApplicationEventMulticasterによって、リスナーにイベントを発行している。
この違いはなんだろう...?

spring-framework/AbstractApplicationContext.java at master · spring-projects/spring-framework · GitHub

ApplicationListener

イベントを受信できるインターフェイスである。
Spring4.2以降は、このインターフェイスは使用せずに@Eventlistenerを付与するだけで良い。

@Component
public class SampleListener {

    @Autowired
    private SamplePublisher samplePublisher;

    @EventListener
    public void onMyEvent (SampleEvent event) {
        System.out.println("Thread : " + Thread.currentThread().getName() + " event received: " + event.getMsg());
    }

}

ユースケース

データを読込、加工して、DBに登録するアプリケーションを例に考えて見る。

ApplicationEventを使用しない場合

読込処理 -> 加工処理 -> 登録処理

なんの変哲も無い、良くあるプログラムである。

ApplicationEventを使用した場合

読込処理 -> 加工処理 -> ApplicationEvent -> 登録処理

加工処理と登録処理の間にApplicationEventを利用した。
こうする事で、両処理はお互いの処理内容まで気にする必要が無くなる。
加工処理は定義されたEventを発行すれば良いし、登録処理は受信したイベントを元に処理を行えば良くなる。また、テストも書きやすくなると思う。