FactoryBean

A FactoryBean<T> is a bean whose job is to make another object: the container hands out what getObject() returns, not the factory itself.

Why

Use it when building an object takes logic that a library wants to keep behind one bean: a client set up from many settings, a proxy, an object from a builder API. In application code a @Bean method is usually simpler.

How the container treats it:

The generator recognizes a @Component class that extends FactoryBean<T>, and a @Bean method that returns one. It records T as the product type.

SmartFactoryBean<T> tells the container more about the product:

Example

import 'package:spring_core_dart/spring_core_dart.dart';

class HttpClient {
  HttpClient(this.baseUrl, this.timeout);
  final String baseUrl;
  final Duration timeout;
}

// Every bean that injects HttpClient gets one configured from properties.
@Component()
class HttpClientFactory extends FactoryBean<HttpClient> {
  HttpClientFactory(
    @Value(r'${api.url}') this.baseUrl,
    @Value(r'${api.timeout-seconds:10}') this.timeoutSeconds,
  );

  final String baseUrl;
  final int timeoutSeconds;

  @override
  HttpClient getObject() =>
      HttpClient(baseUrl, Duration(seconds: timeoutSeconds));
}

@Service()
class Catalog {
  Catalog(this.client); // the product, not the factory
  final HttpClient client;
}

class Connection {
  static Connection open() => Connection();
}

// The connection is opened at startup, not on first use.
@Component()
class ConnectionFactory extends SmartFactoryBean<Connection> {
  @override
  Connection getObject() => Connection.open();

  @override
  bool get isEagerInit => true;
}
final client = context.getBean<HttpClient>();                // the product
final same = context.getBeanByName('httpClientFactory');     // the product
final factory = context.getBeanByName('&httpClientFactory'); // the factory

Members

FactoryBean<T>:

Member Default Meaning
T getObject() required Creates or returns the product.
bool get isSingleton true Whether getObject() returns the same instance every time; the container then caches it.
Type get objectType T The product type. Used for a factory added with registerSingleton.

SmartFactoryBean<T> adds:

Member Default Meaning
bool get isPrototype false Whether every getObject() call returns an independent instance.
bool get isEagerInit false Whether the product of a non-lazy singleton factory is created at startup.
bool supportsType(Type type) objectType or Object Whether the factory serves a product for lookups by type.
Object? getObjectForType(Type type) getObject() when supported The product for a lookup by type. null fails the lookup.

BeanFactory.factoryBeanPrefix is the & prefix.

In Spring (Java)

@Component
class HttpClientFactory implements FactoryBean<HttpClient> {
  @Override
  public HttpClient getObject() { return HttpClient.newHttpClient(); }

  @Override
  public Class<?> getObjectType() { return HttpClient.class; }
}

HttpClient client = context.getBean(HttpClient.class);
Object factory = context.getBean("&httpClientFactory");

Differences that matter:

See also