Pod constructor

const Pod({
  1. String? value,
  2. AutowireMode autowireMode = AutowireMode.NO,
  3. List<String> initMethods = const [],
  4. List<String> destroyMethods = const [],
  5. bool enforceInitMethods = false,
  6. bool enforceDestroyMethods = false,
})

Marks a method as a pod provider, enabling it to participate in the dependency injection (DI) lifecycle of the application.

The method annotated with @Pod should return an instance of a component, service, or configuration object. This returned value is automatically registered in the application’s DI container and, by default, managed as a singleton.


🔧 How It Works:

  • The enclosing class is typically annotated with @Configuration or @AutoConfiguration.
  • During application startup, all methods annotated with @Pod are executed, and their return values are registered in the application context.
  • These pods are then available for injection into other classes via constructor injection, factory injection, or field injection (depending on the framework).

📌 Features:

  • Default lifecycle is singleton (created once and reused).
  • Supports lazy initialization depending on the framework’s DI engine.
  • May support pod naming or conditional creation in extended versions.

🧪 Example:

@Configuration()
class AppConfig {

  @Pod()
  Logger createLogger() {
    return Logger('AppLogger');
  }

  @Pod()
  HttpClient httpClient(Logger logger) {
    return HttpClient(logger: logger);
  }
}

In the example above:

  • createLogger() returns a Logger instance registered as a pod.
  • httpClient() depends on Logger, which is automatically injected by the container.

🔄 Pod Lifecycle (Simplified):

- Framework initializes configuration class
- All @Pod methods are executed
- Results are cached as singleton pods
- Pods are injected into constructors or other pods as needed

🔥 Advanced Use Cases (Possible Extensions):

  • Conditional pods: @ConditionalOnMissingPod, @Profile('dev')
  • Scoped pods: e.g., per request, per session (via @Scope)
  • Named pods: @Pod(name: 'myLogger')

These can be added through optional parameters or decorators in future.


❗ Constraints:

  • The method must be non-private.
  • The method must return a value; void is not allowed.
  • Must be defined within a class marked with @Configuration, @AutoConfiguration, etc.
  • Cyclic dependencies must be handled explicitly or avoided.

✅ Usage Recommendations:

  • Prefer pod methods over manual instantiation in app code.
  • Keep logic inside pod methods minimal — do initialization but not business logic.
  • Group related pods in separate configuration classes for clarity.

  • @Configuration – Marks the containing class as a source of pod definitions.
  • @AutoConfiguration – Similar but auto-discovered.
  • @Aspect – Used for cross-cutting concerns.
  • @Inject, @Autowired – For consuming/injecting defined pods.

🎯 Target:

Can only be applied to methods:

@Pod()
MyService myService() => MyService();

Pod annotation for pod definition methods

This annotation marks a method as a pod producer.

Example Usage:

@Configuration()
class DatabaseConfig {
  @Pod()
  @Scope('singleton')
  DatabaseConnection primaryDatabase() {
    return DatabaseConnection(
      url: 'postgresql://localhost:5432/primary',
      maxConnections: 20,
    );
  }
  
  @Pod('readOnlyDatabase')
  @Scope('prototype')
  DatabaseConnection readOnlyDatabase() {
    return DatabaseConnection(
      url: 'postgresql://localhost:5432/readonly',
      readOnly: true,
    );
  }
}

Implementation

const Pod({
  this.value,
  this.autowireMode = AutowireMode.NO,
  this.initMethods = const [],
  this.destroyMethods = const [],
  this.enforceInitMethods = false,
  this.enforceDestroyMethods = false
});