auto-di 0.1.0

Ergonomic async-aware automatic dependency injection for Rust
Documentation

auto-di

Spring-style dependency injection for Rust, backed by a global inventory registry and async-safe initialization.

Components and constructor injection

use std::sync::Arc;
use auto_di::{repository, service};

trait Users: Send + Sync {}

#[repository(name = "postgres", primary)]
fn users() -> Arc<dyn Users> {
    Arc::new(PostgresUsers)
}

#[service(eager, post_construct = "start", pre_destroy = "stop")]
impl UserService {
    fn new(#[qualifier("postgres")] users: Arc<dyn Users>) -> Self {
        Self { users }
    }

    async fn start(&self) {}
    async fn stop(&self) {}
}

#[component], #[service], #[repository], and #[singleton] share these options:

  • name = "..."
  • primary
  • scope = "singleton" | "prototype" | "request"
  • eager
  • profile = "development"
  • condition = "ENV_KEY" or condition = "ENV_KEY=value"
  • post_construct = "async_method"
  • pre_destroy = "async_method"

Constructors accept Arc<T>, Option<Arc<T>>, Vec<Arc<T>>, Provider<T>, and Lazy<T>. Both sync and async constructors are supported.

Configuration beans

#[derive(Default)]
struct Beans;

#[configuration]
impl Beans {
    #[bean]
    fn config(&self) -> Config { Config::default() }

    #[bean(name = "main", primary)]
    async fn database(&self, config: Arc<Config>) -> Database {
        Database::connect(&config).await
    }
}

Environment properties

#[configuration_properties("database")]
struct DatabaseProperties {
    url: String,       // DATABASE_URL
    pool_size: usize,  // DATABASE_POOL_SIZE
}

Application and request scopes

#[application]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let service = auto_di::resolve::<UserService>().await?;
    Ok(())
}

let request = auto_di::global_container()?.request_context();
let bean = request.resolve::<RequestBean>().await?;

Active profiles come from comma-separated APP_PROFILES, or can be selected explicitly with Container::with_profiles(...).