
# @PreDestroy

`@PreDestroy()` marks a method the container calls when a bean is destroyed.

## Why

Use it to release what the bean holds: flush a buffer, close a file, cancel a timer, end a subscription.

When it runs:

- for a singleton, when the context closes (`close()` or `closeAsync()`). Each bean is destroyed after the beans that depend on it;
- for a bean of a custom scope, when its scope ends;
- for a prototype, never. The container does not track prototypes, as in Spring.

The method takes no arguments. It may return a `Future`. `closeAsync()` waits for it; `close()` logs it and goes on without waiting.

Errors thrown during destruction are logged and collected. They do not stop the shutdown of the other beans.

The order of destruction for one bean:

1. `DestructionAwareBeanPostProcessor.postProcessBeforeDestruction`;
2. **`@PreDestroy` methods**;
3. `DisposableBean.destroy`;
4. the `destroyMethod` of `@Bean` (by default an inferred `close`, `shutdown` or `dispose`).

## Example

```dart
import 'dart:async';
import 'dart:io';

import 'package:spring_core_dart/spring_core_dart.dart';

// Buffers log lines and writes them in batches.
@Component()
class EventBuffer {
  final _lines = <String>[];
  Timer? _timer;

  @PostConstruct()
  void start() =>
      _timer = Timer.periodic(const Duration(seconds: 10), (_) => _write());

  void add(String line) => _lines.add(line);

  void _write() {
    File('events.log').writeAsStringSync(
      _lines.map((l) => '$l\n').join(),
      mode: FileMode.append,
    );
    _lines.clear();
  }

  // Runs on context.close(): nothing is lost at shutdown.
  @PreDestroy()
  void flush() {
    _timer?.cancel();
    _write();
  }
}
```

```dart
void main() {
  final context = ApplicationContext.run([appBeans])
    // Closes the context on Ctrl+C or SIGTERM, so @PreDestroy runs.
    ..registerShutdownHook();
  context.getBean<EventBuffer>().add('started');
}
```

## Parameters

None.

## In Spring (Java)

The Jakarta annotation `jakarta.annotation.PreDestroy`:

```java
@Component
class EventBuffer {
  @PreDestroy
  void flush() { ... }
}
```

Differences that matter: a `Future`-returning method is supported and awaited by `closeAsync()`. `registerShutdownHook()` reacts to SIGINT and SIGTERM and does nothing on the web.

## See also

- [@PostConstruct](post-construct.md)
- [Lifecycle and SmartLifecycle](lifecycle.md)
- [@Scope](scope.md)
- [@Bean](bean.md) (`destroyMethod`)
- [ApplicationContext](application-context.md) (`close`, `closeAsync`, `registerShutdownHook`)
