@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

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];
}
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:

@Component
class PriceCache {
  @Autowired PriceSource source;

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

Differences that matter:

See also