@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:
- the method must be public, take no parameters and not be generic;
- the class must be extendable from the generated library: not
final,sealedorinterface, with a public generative constructor; - the class must not be a full-mode
@Configurationclass.
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:
- Spring creates the subclass with CGLIB at run time. Here the generator writes it, so the class must be extendable from another library and the methods must be public.
- Spring lets lookup methods take arguments, passed to the bean's constructor. Here lookup methods take no parameters: inject an
ObjectProvider<T>or a factory and pass the values yourself. - An abstract class may have no abstract members besides its lookup methods (a build error; Spring fails only when one is called).
See also
- ObjectProvider
- @Scope
- @Lazy
- Jakarta annotations (
Provider)