@Lookup

@Lookup() marks a method that returns a bean of the container on every call.

Why

A singleton receives its dependencies once, when it is created. If it needs a fresh prototype bean each time (a command, a unit of work), injecting the prototype does not help: the singleton would keep the first instance.

A @Lookup method solves this. Every call returns the bean of the method's return type, or the bean named by @Lookup('name'). A nullable return type gives null when no bean of the type exists.

The bean is created as a generated subclass that overrides the method. So the method may be abstract, and the class may be abstract too: an abstract @Component class with @Lookup methods is a bean, unlike other abstract classes. A concrete method works too; its body never runs.

An ObjectProvider does the same job without a subclass and without the limits below. Prefer it when you can change the constructor.

Limits, checked at build time:

Example

import 'package:spring_core_dart/spring_core_dart.dart';

// A new Command for every use: it holds per-run state.
@Component()
@Scope(ScopeType.prototype)
class Command {
  final steps = <String>[];
  void run() => steps.add('ran');
}

@Component('auditLog')
class AuditLog {
  void record(String event) {}
}

@Component()
abstract class CommandManager {
  // A new Command per call.
  @Lookup()
  Command createCommand();

  // The bean named `auditLog`.
  @Lookup('auditLog')
  AuditLog auditLog();

  void process() {
    createCommand().run();
    auditLog().record('processed');
  }
}

Parameters

Name Type Default Meaning
value (positional) String? null The name or alias of the bean to return. null looks the bean up by the method's return type.

In Spring (Java)

@Component
public abstract class CommandManager {
  @Lookup
  protected abstract Command createCommand();

  @Lookup("auditLog")
  protected abstract AuditLog auditLog();
}

Differences that matter:

See also