
# コンテキストイベント

コンテキストイベントは、アプリケーションコンテキストが自分のライフサイクル (refreshed、started、stopped、paused、restarted、closed) について発行するイベントです。

## 使う理由

処理によっては、一つの Bean が作られたときではなく、コンテキストのライフサイクルの特定の時点で行う必要があります。

- すべての Bean がそろった後にキャッシュを温める、または「ready」とログに出す: `ContextRefreshedEvent`。
- シャットダウンの前、すべての Bean がまだ動くうちに状態を保存する: `ContextClosedEvent`。
- Flutter アプリがバックグラウンドにある間など、バックグラウンド処理の一時停止や再開に反応する: `ContextPausedEvent`、`ContextRestartedEvent`。

アプリケーションはこれらのイベントを受け取るだけで、作ることはありません。`@EventListener` メソッド、`ApplicationListener`、または `context.addListener` で受け取ります。一つの Bean の初期化なら `@PostConstruct` のほうが簡単です。

## 例

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

abstract interface class SessionRepository {
  void saveAll();
}

@Component()
@Log()
class Lifecycle {
  Lifecycle(this.sessions);
  final SessionRepository sessions;

  // すべての eager なシングルトンが存在し、自動起動の Bean が動いている。
  @EventListener()
  void onReady(ContextRefreshedEvent event) =>
      log.info('ready: ${event.applicationContext.id}');

  // close() の最初の段階。ここではまだ他の Bean を使える。
  @EventListener()
  void onClose(ContextClosedEvent event) => sessions.saveAll();
}
```

基底クラス `ApplicationContextEvent` を受け取ると、すべてのコンテキストイベントを受け取れます:

```dart
@Component()
@Log()
class ContextLog {
  @EventListener()
  void on(ApplicationContextEvent event) =>
      log.info('${event.runtimeType} of ${event.applicationContext.id}');
}
```

## メンバー

| イベント | 発行されるとき | 補足 |
|---|---|---|
| `ApplicationContextEvent` | (基底クラス) | `applicationContext` はイベントを起こしたコンテキストで、`source` と同じオブジェクト。 |
| `ContextRefreshedEvent` | `refresh()` の最後の段階。すべての eager なシングルトンが存在し、自動起動のライフサイクル Bean が動いている。 | リスナーが例外を投げるとリフレッシュは失敗する (マルチキャスターにエラーハンドラーがある場合を除く)。 |
| `ContextStartedEvent` | 明示的な `start()` の後。通常は `stop()` の後。 | 最初の起動時には発行されない。 |
| `ContextStoppedEvent` | `stop()` の後。動いていたライフサイクル Bean が止まっている。 | Bean はまだ存在する。`close()` では発行されない。 |
| `ContextRestartedEvent` | `restart()` の後。自動起動のライフサイクル Bean が再び動く。 | `ContextStartedEvent` のサブクラス。Spring 7 で追加。 |
| `ContextPausedEvent` | `pause()` または `pauseAsync()` の後。一時停止可能なライフサイクル Bean が止まっている。 | `ContextStoppedEvent` のサブクラス。Spring 7 で追加。 |
| `ContextClosedEvent` | `close()` の最初の段階。すべての Bean がまだ使える。 | リスナーのエラーはログに出され、シャットダウンは続く。 |

子コンテキストで発行されたイベントは、親のリスナーにも届きます。区別が必要なときは `applicationContext` を比較してください。

## Spring (Java) との対応

```java
@Component
class Lifecycle {
  @EventListener
  void onReady(ContextRefreshedEvent event) { ... }

  @EventListener
  void onClose(ContextClosedEvent event) { sessions.saveAll(); }
}
```

イベントとその順序は Spring 7 と同じです。Spring Boot (`spring_boot_dart`) を使う場合、`ApplicationReadyEvent` はランナーの後に発行されるため、「アプリケーションの準備ができた」時点としては通常 `ContextRefreshedEvent` より適しています。

## 関連項目

- [イベント](index.md)
- [@EventListener](event-listener.md)
- [ApplicationEvent](application-event.md)
- [ApplicationContext](../beans/application-context.md)
- [@PostConstruct](../beans/post-construct.md)
