
# ConfigurableListableBeanFactory

`ConfigurableListableBeanFactory` is the full interface of the bean container: besides handing out beans, it lets code change bean definitions and the container's setup before any bean is created.

## Why

Most applications never need it. Beans are declared with annotations, and the generator registers them. It is for code that adjusts the container itself:

- a [BeanFactoryPostProcessor](bean-factory-post-processor.md) that makes some beans lazy or checks that a bean exists;
- code that registers an object that is not a bean, such as one built in `main`, so beans can inject it;
- code that registers a custom scope or adds a bean post-processor;
- a test or tool that uses a container without a context.

You get it in two places: as the argument of `BeanFactoryPostProcessor.postProcessBeanFactory`, and as `context.beanFactory`. The latter is available before `refresh()`.

`DefaultListableBeanFactory` is its implementation. Every application context owns one. Create one yourself for a small container without a context: a command-line tool, a test, a library that wires a few objects. Without a context there is no environment, no event delivery, no detection of post-processor beans and no lifecycle management.

### The interfaces it combines

| Interface | Role |
|---|---|
| `BeanFactory` | Lookups: `getBean`, `findBean`, `getBeanByName`, `getBeanProvider`, `containsBean`, `isTypeMatch`, `getType`. |
| `ListableBeanFactory` | Listing: `getBeanNamesForType`, `getBeansOfType`, `getSortedBeans`, `getBeanNamesForAnnotation`, `findAnnotationOnBean`. |
| `HierarchicalBeanFactory` | `parentBeanFactory`, `containsLocalBean`. |
| `SingletonBeanRegistry` | `registerSingleton`, `getSingleton`, `containsSingleton`, `singletonNames`. |
| `ConfigurableBeanFactory` | Setup: post-processors, scopes, aliases, conversion, placeholder resolvers, dependency records, destruction. |
| `AutowireCapableBeanFactory` | `autowireBean`, `initializeBean`, `destroyBean` for objects the container did not create. |

`DefaultListableBeanFactory` also implements `BeanDefinitionRegistry` (`registerBeanDefinition`, `removeBeanDefinition`, ...).

## Example

In a post-processor:

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

// The slow `reports` bean starts on first use; `auditLog` must exist.
@Component()
class AdjustBeans implements BeanFactoryPostProcessor {
  @override
  void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    beanFactory.getBeanDefinition('reports').lazy = true;
    if (!beanFactory.containsBeanDefinition('auditLog')) {
      throw StateError('An auditLog bean is required');
    }
  }
}
```

Before the context starts:

```dart
abstract interface class Clock {
  DateTime now();
}

class SystemClock implements Clock {
  @override
  DateTime now() => DateTime.now();
}

void main() {
  final context = AnnotationConfigApplicationContext([appBeans]);
  context.beanFactory
    // An object built here, injectable as a Clock.
    ..registerSingleton(
      'clock',
      SystemClock(),
      types: const [SystemClock, Clock],
    )
    // A library expects 'primaryDb'; the application named it 'dataSource'.
    ..registerAlias('dataSource', 'primaryDb')
    ..registerScope('screen', SimpleMapScope());
  context.refresh();
}
```

A container without a context:

```dart
class Repo {}

class Service {
  Service(this.repo);
  final Repo repo;
}

void main() {
  final factory = DefaultListableBeanFactory()
    ..registerBeanDefinition(
      BeanDefinition<Repo>(name: 'repo', create: (_) => Repo()),
    )
    ..registerBeanDefinition(
      BeanDefinition<Service>(
        name: 'service',
        dependencies: const [Dependency(Repo)],
        create: (r) => Service(r.dependency<Repo>()),
      ),
    )
    ..validateBeanGraph()
    ..preInstantiateSingletons();

  final service = factory.getBean<Service>();
  factory.destroySingletons();
}
```

## Members

Specific to `ConfigurableListableBeanFactory`:

| Member | Meaning |
|---|---|
| `getBeanDefinition(name)` | The definition, to read or change. Its mutable fields (`scope`, `lazy`, `primary`, `fallback`, `autowireCandidate`, `defaultCandidate`, `order`, `description`) apply to beans created afterwards. |
| `registerResolvableDependency(type, value)` | Makes `value` injectable where exactly `type` is asked for, without making it a bean. |
| `validateBeanGraph()` | Checks every dependency, required placeholder, `@DependsOn` name and cycle without creating a bean. |
| `preInstantiateSingletons()` | Creates every non-lazy singleton, then calls `SmartInitializingSingleton.afterSingletonsInstantiated`. |
| `preInstantiateSingletonsAsync()` | The same, awaiting init callbacks that return a `Future`. |
| `freezeConfiguration()`, `isConfigurationFrozen` | A hint that the definitions will not change, so lookups can be cached. |

From `ConfigurableBeanFactory`:

| Member | Meaning |
|---|---|
| `addBeanPostProcessor(processor)`, `beanPostProcessorCount` | Adds a [BeanPostProcessor](bean-post-processor.md) for beans created from now on. |
| `registerScope(name, scope)`, `registeredScopeNames`, `getRegisteredScope(name)` | Custom scopes for `@Scope(name)`. |
| `registerAlias(name, alias)` | A second name for a bean. |
| `parentBeanFactory` | The factory asked when a lookup finds nothing here. Settable. |
| `conversionService` | Converts `@Value` results to the target type. Settable. |
| `addEmbeddedValueResolver(resolver)`, `resolveEmbeddedValue(value)` | The chain that resolves `${...}` placeholders. |
| `beanExpressionResolver` | Evaluates `#{...}` expressions. Settable. |
| `registerDependentBean(beanName, dependentBeanName)`, `getDependentBeans(name)`, `getDependenciesForBean(name)` | The recorded dependencies, which decide the destruction order. |
| `isCurrentlyInCreation(name)`, `isFactoryBean(name)` | Questions about one bean. |
| `destroySingletons()`, `destroySingletonsAsync()`, `destructionErrors` | Destroys the created singletons. |
| `destroyScopedBean(name)` | Destroys the current instance of a bean in a custom scope. |

From `SingletonBeanRegistry`: `registerSingleton(name, singleton, {types})` registers a ready-made object. It is found by its name and by the listed `types` (its runtime type by default). No injection, init or destroy callback runs for it.

On `DefaultListableBeanFactory` only: the constructor takes an optional `parentBeanFactory`, and `allowBeanDefinitionOverriding` (`false` by default) lets a definition replace another with the same name.

## In Spring (Java)

```java
@Component
class AdjustBeans implements BeanFactoryPostProcessor {
  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) {
    factory.getBeanDefinition("reports").setLazyInit(true);
  }
}

ConfigurableListableBeanFactory factory = context.getBeanFactory();
factory.registerSingleton("clock", new SystemClock());
factory.registerScope("screen", new SimpleThreadScope());
```

Differences that matter:

- Definitions carry closures and their lookup types instead of class names. There is no reflection.
- `registerSingleton` must list every type the object should be found by. Spring finds the supertypes by reflection.
- `validateBeanGraph()` has no Spring counterpart. Spring finds missing beans and cycles only while creating beans.
- Circular references are always an error. There are no early singleton references.
- `getBean<T>({qualifier})` and `getBeanByName(name)` replace the overloads of `getBean`.

## See also

- [BeanFactoryPostProcessor](bean-factory-post-processor.md)
- [BeanPostProcessor](bean-post-processor.md)
- [ApplicationContext](application-context.md) (`beanFactory`)
- [ObjectProvider](object-provider.md)
- [FactoryBean](factory-bean.md)
- [@Scope](scope.md)
- [@Configurable](configurable.md)
