injection 0.1.1

A lightweight dependency injection container for Rust applications
Documentation
# Injection - 依赖注入容器


Injection 是一个基于宏的异步依赖注入容器,专为 Rust 应用程序设计。它使用 inventory 宏自动收集 Bean 定义,支持异步初始化和配置管理。

## 功能特性


- **自动注册**:使用 `#[derive(Component)]``#[derive(Service)]` 宏自动注册组件
- **异步初始化**:支持异步工厂函数初始化组件
- **配置管理**:通过 `#[configuration]` 宏从配置文件加载配置
- **依赖注入**:自动解决依赖关系,支持字段级注入
- **线程安全**:所有组件都是 `Send + Sync`- **延迟初始化**:使用 `OnceCell` 实现懒加载
- **Axum 集成**:Service 宏支持 Axum 提取器,可直接在路由中使用

## 安装


在 `Cargo.toml` 中添加:

```toml
[dependencies]
injection = { path = "*" }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
serde = { version = "1", features = ["derive"] }
```

## 基本用法


### 1. 定义组件


使用 `#[derive(Component)]` 或 `#[derive(Service)]` 宏标记结构体:

```rust
use injection::{Component, Service};
use serde::Deserialize;

// 简单的数据访问对象
#[derive(Component, Clone)]

struct DatabaseConnection {
    url: String,
}

impl DatabaseConnection {
    fn new() -> Self {
        DatabaseConnection {
            url: "localhost:5432".to_string(),
        }
    }
}

// 服务层组件,自动注入 DatabaseConnection
#[derive(Component)]

struct UserService {
    db: DatabaseConnection,
}

impl UserService {
    fn get_user(&self, id: u32) -> String {
        format!("User {} from {:?}", id, self.db.url)
    }
}

// Service 宏还支持 Axum 提取器,可直接在路由中使用
#[derive(Service, Clone)]

struct AppController {
    user_service: UserService,
}
```

### 2. 初始化容器和使用组件


```rust
use injection::InjectionContainer;

#[tokio::main]

async fn main() {
    // 初始化容器(必须在异步上下文中)
    InjectionContainer::init(|| {
        // 可选的初始化回调
        println!("容器初始化完成");
    }).await;
    
    // 同步获取组件(组件必须已预热完成)
    let user_service = InjectionContainer::get::<UserService>();
    println!("{}", user_service.get_user(1));
    
    // 或者异步获取组件
    let app_controller = InjectionContainer::get_async::<AppController>().await;
}
```

### 3. 使用配置


创建配置文件 `application.toml`:

```toml
[database]
host = "localhost"
port = 5432
name = "mydb"

[server]
port = 8080
```

定义配置结构体:

```rust
use injection::{configuration, Component};
use serde::Deserialize;

// 使用 #[configuration] 宏标记配置结构体
// 可以指定 prefix 参数,默认为结构体名称的下划线格式
#[configuration(prefix = "database")]

#[derive(Debug, Deserialize, Clone)]

struct DatabaseConfig {
    host: String,
    port: u16,
    name: String,
}

// 如果不指定 prefix,默认使用结构体名称的下划线格式
// 例如:ServerConfig 默认为 "server_config"
#[configuration]

#[derive(Debug, Deserialize, Clone)]

struct ServerConfig {
    port: u16,
}

// 在组件中使用配置
#[derive(Component)]

struct DatabasePool {
    // 使用 #[config] 属性从配置加载字段
    #[config]
    config: DatabaseConfig,
}

impl DatabasePool {
    fn connection_string(&self) -> String {
        format!("{}:{}:{}", self.config.host, self.config.port, self.config.name)
    }
}
```

## 高级用法


### 使用 init 宏


`#[init]` 宏可以为异步函数自动生成无参版本,支持依赖注入:

```rust
use injection::{init, Component};

// 原始异步函数,参数会自动注入
#[init]

async fn initialize_database(
    #[config] config: DatabaseConfig,  // 从配置加载
) -> DatabasePool {
    DatabasePool::connect(&config.connection_string()).await
}

// 宏会生成一个 __initialize_database 无参函数
// 自动注入所有依赖并调用原始函数
```

### 自定义初始化逻辑


```rust
use injection::Component;

#[derive(Component)]

struct Cache {
    capacity: usize,
}

impl Cache {
    fn new() -> Self {
        Cache { capacity: 1000 }
    }
}

// 为单元结构体提供自定义实现
impl Component for Cache {
    fn component_name() -> &'static str {
        "cache"
    }

    async fn from_container() -> &'static Self {
        Box::leak(Box::new(Cache::new()))
    }
}
```

## API


### InjectionContainer


- `async init<F: FnOnce()>(init_fn: impl Into<Option<F>>)` - 异步初始化容器,可选的初始化回调
- `instance()` - 获取容器实例(同步)
- `get<T: Component>()` - 获取组件(同步,要求组件已初始化)
- `get_async<T: Component>()` - 获取组件(异步,可等待未初始化的组件)

### 

#### `#[derive(Component)]`

为结构体自动生成 Component trait 实现。

支持的字段属性:
- `#[config]` - 从配置文件加载字段值
- `#[init("fn_name")]` - 使用指定的异步函数初始化字段

#### `#[derive(Service)]`

与 Component 相同,但额外实现 Axum 提取器,可在路由处理器中直接使用。

#### `#[configuration(prefix = "xxx")]`

为配置结构体实现 Configure trait。
- 可选参数 `prefix` 指定配置文件中的键前缀
- 默认使用结构体名称的下划线格式(驼峰转下划线)
- 示例:
  - `#[configuration(prefix = "database")]` - 明确指定前缀为 "database"
  - `#[configuration]` - 使用默认前缀,如 `ServerConfig` -> "server_config"

#### `#[init]`

为异步函数生成无参版本,自动注入依赖。
- 支持 `#[config]` 参数属性,从配置加载参数

## 错误处理


- 容器未初始化时调用 `get()` 会 panic
- 获取不存在的组件会 panic
- Bean 无法 downcast 会 panic
- 配置文件不存在会使用默认值或使用回退配置

## 特性标志


- `full` - 启用所有功能(默认)
- `clap-config` - 支持命令行参数解析配置文件路径
- `config` - 启用配置管理功能
- `serde` - 启用序列化/反序列化支持

## 完整示例


```rust
use injection::{Component, Service, configuration, InjectionContainer};
use serde::Deserialize;

// 配置
#[configuration]

#[derive(Debug, Deserialize, Clone)]

struct ServerConfig {
    port: u16,
}

// 数据库连接
#[derive(Component, Clone)]

struct Database {
    url: String,
}

// 用户服务
#[derive(Component)]

struct UserService {
    db: Database,
}

// 控制器(可用于 Axum)
#[derive(Service)]

struct UserController {
    user_service: UserService,
    #[config]
    config: ServerConfig,
}

#[tokio::main]

async fn main() {
    // 初始化容器
    InjectionContainer::init(|| {
        println!("应用启动");
    }).await;
    
    // 使用组件
    let controller = InjectionContainer::get::<UserController>();
    println!("服务器端口:{}", controller.config.port);
}
```

## 许可证


MIT