
# @PostConstruct

`@PostConstruct()` marks a method the container calls once a bean is fully injected, before anyone uses it.

## Why

Use it for setup that needs the injected values: warming a cache, checking settings, opening a connection. The constructor is too early when fields or setters are injected, because they are set after the constructor returns.

The method takes no arguments. It may return a `Future`. Then start the context with `refreshAsync()` or `ApplicationContext.runAsync`, which wait for it. The synchronous `refresh()` fails for such a method.

The order of creation for one bean:

1. constructor;
2. injected fields, setters and `@Autowired` methods;
3. aware callbacks (`BeanNameAware`, `ApplicationContextAware`, ...);
4. `postProcessBeforeInitialization` of the bean post-processors;
5. **`@PostConstruct` methods**;
6. `InitializingBean.afterPropertiesSet`;
7. the `initMethod` of `@Bean`;
8. `postProcessAfterInitialization`.

## Example

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

abstract interface class PriceSource {
  Future<Map<String, double>> loadAll();
}

const log = SpringLog('shop.prices');

@Component()
class PriceCache {
  @Autowired()
  late final PriceSource source;

  final _prices = <String, double>{};

  // The field `source` is set by now. Returning a Future: start the
  // context with ApplicationContext.runAsync or refreshAsync.
  @PostConstruct()
  Future<void> warmUp() async {
    _prices.addAll(await source.loadAll());
    log.info('loaded ${_prices.length} prices');
  }

  double? price(String sku) => _prices[sku];
}
```

```dart
Future<void> main() async {
  final context = await ApplicationContext.runAsync([appBeans]);
  // every @PostConstruct has completed here
  await context.closeAsync();
}
```

## Parameters

None.

## In Spring (Java)

The Jakarta annotation `jakarta.annotation.PostConstruct`:

```java
@Component
class PriceCache {
  @Autowired PriceSource source;

  @PostConstruct
  void warmUp() { ... }
}
```

Differences that matter:

- Spring has no asynchronous init methods. Here a `Future` is allowed and awaited by `refreshAsync()`, one bean after another.
- A bean created after startup (lazy, prototype, scoped) needs a synchronous `@PostConstruct`.
- The annotation is part of `spring_core_dart.dart`, not of a separate Jakarta package.

## See also

- [@PreDestroy](pre-destroy.md)
- [Lifecycle and SmartLifecycle](lifecycle.md)
- [Aware interfaces](aware.md)
- [@Bean](bean.md) (`initMethod`)
- [ApplicationContext](application-context.md) (`runAsync`, `refreshAsync`)
