@Lazy

@Lazy() delays the creation of a bean, or of what an injection point receives, until it is first used.

Why

Singletons are created at startup. That shows configuration errors early, but it also creates beans that many runs never need. @Lazy() has two uses.

On a bean (a class, a @Bean method, or a configuration class for all its @Bean methods): the singleton is created on the first lookup or injection instead of at startup. Use it for expensive beans that are rarely used, such as a report generator. @Lazy(false) makes one bean eager where its configuration class or the scan (lazyInit: true) would make it lazy.

On an injection point (a constructor parameter, a field, a setter): a generated proxy is injected instead of the bean. The proxy finds the bean on every call. This helps in two cases:

Even when lazy, the bean must exist and be unique. refresh() checks that at startup.

Limits on an injection point: the type must be implementable from generated code (an interface, or a class without private members, not generic), and the point must not be nullable. Otherwise use ObjectProvider.

Example

import 'package:spring_core_dart/spring_core_dart.dart';

// Created on the first getBean or injection, not at startup.
@Component()
@Lazy()
class ReportGenerator {
  String render() => 'report';
}

abstract interface class Books {
  String find(String isbn);
  List<String> findAll(List<String> isbns);
}

// Calls through _self go through the proxy, so advice on find()
// (caching, timing) applies to each call.
@Service()
class BookService implements Books {
  BookService(@Lazy() this._self);
  final Books _self;

  @override
  String find(String isbn) => 'Book $isbn';

  @override
  List<String> findAll(List<String> isbns) =>
      [for (final isbn in isbns) _self.find(isbn)];
}

class PdfExporter {
  List<int> export(String text) => text.codeUnits;
}

// Every @Bean method of this class is lazy, except clock().
@Configuration()
@Lazy()
class ToolsConfig {
  @Bean()
  PdfExporter pdfExporter() => PdfExporter();

  @Bean()
  @Lazy(false)
  DateTime Function() clock() => DateTime.now;
}

Parameters

Name Type Default Meaning
value (positional) bool true Whether the bean or the injection point is lazy.

In Spring (Java)

@Component
@Lazy
class ReportGenerator { ... }

@Service
class BookService {
  @Lazy @Autowired private BookService self;
}

Differences that matter:

See also