
# @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](object-provider.md) 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`, `sealed` or `interface`, with a public generative constructor;
- the class must not be a full-mode `@Configuration` class.

## Example

```dart
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)

```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](object-provider.md)
- [@Scope](scope.md)
- [@Lazy](lazy.md)
- [Jakarta annotations](jakarta.md) (`Provider`)
