
# イベント

イベントは、ある Bean が「何かが起きた」と知らせ、ほかの任意の数の Bean がそれに反応する仕組みです。

## 使う理由

イベントがなければ、注文サービスがメール送信、在庫、分析のサービスを自分で呼び出すことになります。反応を一つ増やすたびに注文サービスを書き換える必要があります。イベントを使えば、注文サービスは「注文が入った」と発行するだけです。メール、在庫、分析はそれを受け取ります。どちらも相手を知りません。

イベントは、発行側の本来の仕事ではない反応に使います。呼び出し側が結果を必要とする場合は使わず、相手の Bean を直接呼び出してください。

コンテキスト自身も、すべての Bean の準備ができたときの `ContextRefreshedEvent` など、自分についてのイベントを発行します。

## 例

```dart
import 'package:spring_core_dart/spring_core_dart.dart';

// どんなオブジェクトもイベントにできる。基底クラスは不要。
class OrderPlaced {
  const OrderPlaced(this.id, this.total);
  final String id;
  final double total;
}

@Service()
class Orders {
  Orders(this.events);

  // パブリッシャーとしてコンテキスト自身が注入される。
  final ApplicationEventPublisher events;

  void place(String id, double total) =>
      events.publishEvent(OrderPlaced(id, total));
}

@Component()
@Log()
class Analytics {
  // OrderPlaced が発行されるたびに呼ばれる。
  @EventListener()
  void onPlaced(OrderPlaced order) => log.info('order ${order.id}');
}
```

デフォルトでは、リスナーは `publishEvent` の中で実行されるため、発行側はその完了を待ちます。`@Async` を付けると、そのリスナーだけこの動作が変わります。

## ページ一覧

- [@EventListener](event-listener.md): 引数の型のイベントごとに呼ばれる Bean のメソッド。条件と順序の指定も扱います。
- [@Async](async.md): リスナーを `TaskExecutor` 上で実行し、発行側を待たせません。
- [ApplicationEvent](application-event.md): イベントの基底クラス、パブリッシャー、リスナーのインターフェース。
- [コンテキストイベント](context-events.md): コンテキストが自分について発行するイベント (refreshed、started、stopped、closed など)。

## Spring (Java) との対応

```java
@Service
class Orders {
  private final ApplicationEventPublisher events;
  Orders(ApplicationEventPublisher events) { this.events = events; }

  void place(String id, double total) {
    events.publishEvent(new OrderPlaced(id, total));
  }
}

@Component
class Analytics {
  @EventListener
  void onPlaced(OrderPlaced order) { ... }
}
```

モデルは同じです。主な違いは、リスナーの条件が SpEL の文字列ではなく Dart の関数であること、そして `@Async` が `@EventListener` メソッドにしか使えないことです。

## 関連項目

- [Bean](../beans/index.md)
- [ApplicationContext](../beans/application-context.md)
- [ログ](../logging/index.md)
