# injection **Repository Path**: maoly1012/injection ## Basic Information - **Project Name**: injection - **Description**: Injection 是一个轻量级的依赖注入容器,用于 Rust 应用程序。它支持实例注入和类型注入(延迟初始化),能够管理复杂的依赖关系。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-26 - **Last Updated**: 2026-03-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 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::(); println!("{}", user_service.get_user(1)); // 或者异步获取组件 let app_controller = InjectionContainer::get_async::().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(init_fn: impl Into>)` - 异步初始化容器,可选的初始化回调 - `instance()` - 获取容器实例(同步) - `get()` - 获取组件(同步,要求组件已初始化) - `get_async()` - 获取组件(异步,可等待未初始化的组件) ### 宏 #### `#[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::(); println!("服务器端口:{}", controller.config.port); } ``` ## 许可证 MIT