
# BeanFactoryPostProcessor

A `BeanFactoryPostProcessor` runs once at startup, after all bean definitions are registered and before any ordinary bean is created, to inspect or change them.

## Why

Use it to adjust beans you did not declare yourself:

- make a library's bean lazy;
- change a scope, or mark a bean `primary`;
- check that a required bean exists, and fail the start with a clear message.

It sees definitions, not beans. Most applications never need one.

`BeanDefinitionRegistryPostProcessor` extends it. It can also add, remove or replace definitions. Use it when the set of beans is only known at startup: one bean per entry of a configuration file, one per plug-in found. Definitions it registers are seen by every later post-processor. For registering beans in code, a [BeanRegistrar](bean-registrar.md) is usually simpler.

### When they run

During `refresh()`, after the modules are loaded and before the bean graph is checked:

1. the processors added with `context.addBeanFactoryPostProcessor(...)`: `postProcessBeanDefinitionRegistry` of the registry processors;
2. the `BeanDefinitionRegistryPostProcessor` beans, in three phases: `PriorityOrdered`, then `Ordered` or `@Order`, then the rest. The last phase repeats while they register more of themselves;
3. `postProcessBeanFactory` of all registry processors, then of the regular processors added in code;
4. the remaining `BeanFactoryPostProcessor` beans, in the same three phases.

Processors added in code run before the processor beans. One added after `refresh()` never runs.

Avoid creating beans in a post-processor, and keep its own dependencies few. A bean created here is created before the [BeanPostProcessor](bean-post-processor.md)s exist and misses their processing.

## Example

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

abstract interface class Greeter {
  String greet(String name);
}

class German implements Greeter {
  @override
  String greet(String name) => 'Hallo, $name';
}

// The slow `reports` bean of a library starts on first use, not at startup.
@Component()
class MakeReportsLazy implements BeanFactoryPostProcessor {
  @override
  void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    if (beanFactory.containsBeanDefinition('reports')) {
      beanFactory.getBeanDefinition('reports').lazy = true;
    }
  }
}

// Adds a German greeter, written by hand, to the scanned greeters.
@Component()
class GermanRegistrar implements BeanDefinitionRegistryPostProcessor {
  @override
  void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    registry.registerBeanDefinition(
      BeanDefinition<German>(
        name: 'german',
        types: const [German, Greeter],
        create: (_) => German(),
      ),
    );
  }

  @override
  void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {}
}
```

A processor that is not a bean:

```dart
final context = AnnotationConfigApplicationContext([appBeans])
  ..addBeanFactoryPostProcessor(MakeReportsLazy())
  ..refresh();
```

## Members

| Interface | Method | Meaning |
|---|---|---|
| `BeanFactoryPostProcessor` | `postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)` | Inspects or changes the definitions: `scope`, `lazy`, `primary`, `fallback`, `autowireCandidate`, `defaultCandidate`, `order`, `description`. |
| `BeanDefinitionRegistryPostProcessor` | `postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)` | Adds, removes or replaces definitions. Runs before every `postProcessBeanFactory`, its own included. |

`BeanDefinitionRegistry` offers `registerBeanDefinition`, `removeBeanDefinition`, `getBeanDefinition`, `containsBeanDefinition`, `beanDefinitionNames`, `beanDefinitionCount`, `registerAlias`, `removeAlias`, `isAlias` and `isBeanNameInUse`. Registering a name that is already used fails with `BeanDefinitionOverrideException`, unless overriding is allowed.

## In Spring (Java)

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

Differences that matter:

- A definition is a Dart object with a `create` closure, not a class name. Its name is part of it: `registerBeanDefinition(definition)` takes no separate name.
- A hand-written definition that should be found by an interface must list it in `types`. There is no reflection to find the supertypes.
- `PropertySourcesPlaceholderConfigurer` is not needed. The context resolves `${...}` from the environment itself.

## See also

- [BeanPostProcessor](bean-post-processor.md)
- [ConfigurableListableBeanFactory](configurable-listable-bean-factory.md)
- [BeanRegistrar](bean-registrar.md)
- [ApplicationContext](application-context.md) (`addBeanFactoryPostProcessor`)
- [@Lazy](lazy.md)
- [@Scope](scope.md)
