
# @Bean

`@Bean()` marks a method whose return value is a bean.

## Why

Use it when a class cannot carry [@Component](component.md) itself: it comes from another package, or its constructor needs arguments that are not beans. Use it also when creating the object takes code.

The method lives in a [@Configuration](configuration.md) class, or in a `@Component` class ("lite" mode), or is static. Its parameters are injected like constructor parameters, including `@Value` settings and `@Qualifier` selections.

Rules:

- The bean name is the method name, unless `name:` is given.
- The bean type is what the method returns. When the returned expression has a more specific static type than the declared return type, that type is used. `DataSource dataSource() => PooledDataSource()` is registered as `PooledDataSource` and all its supertypes.
- A method declared `T?` may return `null`. The bean then exists by name, but is absent for lookups and injection by type.
- A function type or record type can be a bean too. It is injected by that exact type, into single injection points only.
- At shutdown the container calls a public no-argument `close()`, `shutdown()` or `dispose()` of the declared return type, if there is one. `destroyMethod: ''` turns that off.

## Example

```dart
import 'package:spring_core_dart/spring_core_dart.dart';

class Pool {
  Pool(this.size);
  final int size;
  void open() {}
  void close() {}
}

class Client {
  void close() {}
}

abstract interface class Executor {
  void execute(void Function() task);
}

class SingleExecutor implements Executor {
  @override
  void execute(void Function() task) => task();
}

@Configuration()
class AppConfig {
  // The size comes from the configuration, 4 when unset. open() runs
  // once the pool is created; close() runs at shutdown (inferred).
  // The bean can be found as 'mainPool' or 'pool'.
  @Bean(name: 'mainPool', aliases: ['pool'], initMethod: 'open')
  Pool pool(@Value(r'${pool.size:4}') int size) => Pool(size);

  // This client is shared with code outside the container, so the
  // container must not close it.
  @Bean(destroyMethod: '')
  static Client client() => Client();

  // A second executor that must not get in the way of the main one:
  // it is injected only where @Qualifier('audit') asks for it.
  @Bean(defaultCandidate: false)
  @Qualifier('audit')
  Executor auditExecutor() => SingleExecutor();
}
```

## Parameters

| Name | Type | Default | Meaning |
|---|---|---|---|
| `name` | `String?` | `null` | The bean name. `null` gives the method name. |
| `aliases` | `List<String>` | `[]` | More names the bean can be found under. |
| `initMethod` | `String?` | `null` | A no-argument method of the bean, called once it is injected. For objects you cannot annotate with `@PostConstruct`. |
| `destroyMethod` | `String?` | `Bean.inferMethod` | A no-argument method called when the context closes. The default infers `close`, `shutdown` or `dispose`. An empty string calls nothing. |
| `autowireCandidate` | `bool` | `true` | Whether the bean can be injected by type at all. With `false` it is still found by name. |
| `defaultCandidate` | `bool` | `true` | Whether the bean is injected where only its type is asked for. With `false` it is injected only where a qualifier (`@Qualifier`, the bean name or an alias) selects it. |

## In Spring (Java)

```java
@Configuration
class AppConfig {
  @Bean(name = {"mainPool", "pool"}, initMethod = "open")
  Pool pool(@Value("${pool.size:4}") int size) { return new Pool(size); }

  @Bean(destroyMethod = "")
  static Client client() { return new Client(); }

  @Bean(defaultCandidate = false)
  @Qualifier("audit")
  Executor auditExecutor() { return Executors.newSingleThreadExecutor(); }
}
```

Differences that matter:

- Spring puts aliases in the `name` array after the first name. Here they are a separate `aliases` list.
- Spring knows only the declared return type of a `@Bean` method until the bean is created. Here the generator reads the method body, so `getBean<PooledDataSource>()` and conditions on the bean type work before creation.
- Spring infers `close` and `shutdown` as destroy methods. Here `dispose` is inferred too, because it is the Dart idiom.

## See also

- [@Configuration](configuration.md)
- [@Qualifier](qualifier.md), [@Primary](primary.md)
- [@Scope](scope.md), [@Lazy](lazy.md)
- [@PostConstruct](post-construct.md), [@PreDestroy](pre-destroy.md)
- [FactoryBean](factory-bean.md)
- [@Value](../config/value.md)
