工程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框架即可实现松耦合和高可测试性。