Rudi
Rudi,一个开箱即用的依赖注入框架。
在之前的版本中,不管是依赖的生命周期是 Singleton
还是 Transient
,每次从 Context
中取出的时候,都是一个有所有权的实例,这样的话,对于那些调用 clone
方法开销较大的 Singleton
类型,就会造成性能上的损失。之前的解决办法只能是包一层 Rc
或 Arc
,能用是能用,就是有点麻烦。
在 0.6.0 版本中,我新增了注入 Singleton
的引用的功能。之所以只有 Singleton
,是因为 Singleton
的实例只有一个,取的自然是这个实例的引用;但是对于 Transient
,每次都会创建一个新的实例,取引用的意义不大。
有了这个功能之后,框架的使用体验和性能都有了很大的提升。也算是践行“零抽象开销”的理念了。
示例
use std::cell::RefCell;
use rudi::{Context, Singleton};
// 引用计数
thread_local! {
static COUNT: RefCell<usize> = RefCell::new(0);
}
fn inc_count() {
COUNT.with(|c| {
let mut c = c.borrow_mut();
*c += 1;
});
}
fn get_count() -> usize {
COUNT.with(|c| {
let c = c.borrow();
*c
})
}
// 一个假的 Serialize trait
trait FakeSerialize: Default {}
impl<T: Default> FakeSerialize for T {}
// 一个大的包含所有配置的类型
#[derive(Debug)]
struct AppConfig;
impl Clone for AppConfig {
fn clone(&self) -> Self {
// 如果调用了 AppConfig 的 clone 方法,引用计数加一
inc_count();
Self
}
}
#[Singleton]
impl AppConfig {
// 从文件中读取配置
fn load_file() -> Self {
Self
}
}
// 从大的配置中读取各个配置
impl AppConfig {
fn get<T: FakeSerialize>(&self) -> T {
T::default()
}
}
#[derive(Default, Clone)]
struct DbConfig;
#[Singleton]
impl DbConfig {
// 一个简单的例子
fn new(#[di(ref)] cfg: &AppConfig) -> Self {
cfg.get()
}
}
#[derive(Default, Clone)]
struct RedisConfig;
#[Singleton]
impl RedisConfig {
// 一个使用 Option<&T> 的例子
fn new(#[di(option, ref)] cfg: Option<&AppConfig>) -> Self {
match cfg {
Some(cfg) => cfg.get(),
None => Self,
}
}
}
#[Singleton]
fn Run(_db_config: DbConfig, _redis_config: RedisConfig) {
println!("run!");
}
fn main() {
let mut cx = Context::auto_register();
assert_eq!(get_count(), 0);
cx.resolve::<()>();
// 引用计数一直为 0,说明确实没有调用 clone 方法,都取的是引用
assert_eq!(get_count(), 0);
}
更详细的功能说明可以看文档。
欢迎各位使用,有问题欢迎提 issue,如果觉得好用,可以点个 star。
1
共 0 条评论, 1 页
评论区
写评论还没有评论