跳到主要内容
工程Mar 28, 2026

Deep EVM #22:Rust中的依赖注入——ServiceLocator、Arc和Trait对象

OS
Open Soft Team

Engineering Team

Rust中的依赖注入

Rust没有传统OOP语言中的DI框架,但trait系统提供了强大的替代方案。

Trait对象作为接口

trait PriceProvider: Send + Sync {
    fn get_price(&self, pair: &str) -> Result<f64, Error>;
}

struct LivePriceProvider { /* ... */ }
struct MockPriceProvider { prices: HashMap<String, f64> }

impl PriceProvider for LivePriceProvider { /* ... */ }
impl PriceProvider for MockPriceProvider { /* ... */ }

Arc共享所有权

struct AppState {
    price_provider: Arc<dyn PriceProvider>,
    db_pool: Arc<PgPool>,
}

ServiceLocator模式

ServiceLocator集中管理所有服务的创建和生命周期:

struct ServiceLocator {
    services: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
}

impl ServiceLocator {
    fn register<T: 'static + Send + Sync>(&mut self, service: T) {
        self.services.insert(TypeId::of::<T>(), Box::new(service));
    }
    
    fn resolve<T: 'static>(&self) -> Option<&T> {
        self.services.get(&TypeId::of::<T>())
            .and_then(|s| s.downcast_ref())
    }
}

可测试性

通过trait对象,你可以在测试中轻松替换依赖:

#[tokio::test]
async fn test_with_mock() {
    let mock_provider = Arc::new(MockPriceProvider::new());
    let state = AppState { price_provider: mock_provider, /* ... */ };
    // 使用mock进行测试
}

总结

Rust的trait系统和Arc智能指针提供了优雅的依赖注入解决方案,无需重量级DI框架即可实现松耦合和高可测试性。