ruwebframe 0.1.8

a simple webframe for rust actix-web, based on rudi and rbatis.
Documentation
use std::any::Any;
use std::collections::HashMap;
use std::sync::{Arc, Mutex, OnceLock, RwLock};
use ruwebframe::database;
use ruwebframe::database::TraitRedis;
 
 
enum Entry {
    Factory(Box<dyn Fn() -> Box<dyn Any> + Send + Sync>),
    Singleton {
        factory: Box<dyn Fn() -> Box<dyn Any> + Send + Sync>,
        instance: Mutex<Option<Arc<dyn Any + Send + Sync>>>,
    },
}

pub struct Container {
    items: HashMap<String, Entry>,
}

impl Container {
    pub fn new() -> Self {
        Self { items: HashMap::new() }
    }

    /// 注册多例(每次 get 都 new)
    pub fn register<F, T>(&mut self, key: &str, factory: F)
    where
        F: Fn() -> T + Send + Sync + 'static,
        T: Any + Send + Sync + 'static,
    {
        self.items.insert(
            key.to_string(),
            Entry::Factory(Box::new(move || Box::new(factory()))),
        );
    }

    /// 注册单例(首次 get 时才 new)
    pub fn register_singleton<F, T>(&mut self, key: &str, factory: F)
    where
        F: Fn() -> T + Send + Sync + 'static,
        T: Any + Send + Sync + 'static,
    {
        self.items.insert(
            key.to_string(),
            Entry::Singleton {
                factory: Box::new(move || Box::new(factory())),
                instance: Mutex::new(None),
            },
        );
    }

    /// 获取多例
    pub fn get<T: Any + Clone>(&self, key: &str) -> Option<T> {
        let entry = self.items.get(key)?;
        match entry {
            Entry::Factory(factory) => {
                factory().downcast_ref::<T>().cloned()
            }
            _ => None,
        }
    }

    /// 获取单例(返回 Arc<T>,零拷贝共享)
    pub fn get_singleton<T: Any + Send + Sync>(&self, key: &str) -> Option<Arc<T>> {
        let entry = self.items.get(key)?;
        match entry {
            Entry::Singleton { factory, instance } => {
                let mut guard = instance.lock().ok()?;
                if guard.is_none() {
                    let val = *factory().downcast::<T>()
                        .expect("类型不匹配:注册和解析的类型不一致");
                    *guard = Some(Arc::new(val) as Arc<dyn Any + Send + Sync>);
                }
                guard.as_ref().map(|arc_any| {
                    arc_any.clone().downcast::<T>()
                        .expect("单例 Arc 类型转换失败")
                })
            }
            _ => None,
        }
    }
}

// ==================== 全局封装 ====================

static GLOBAL: OnceLock<RwLock<Container>> = OnceLock::new();

fn global() -> &'static RwLock<Container> {
    GLOBAL.get_or_init(|| RwLock::new(Container::new()))
}

/// 全局注册多例
pub fn register<F, T>(key: &str, factory: F)
where
    F: Fn() -> T + Send + Sync + 'static,
    T: Any + Send + Sync + 'static,
{
    global().write().unwrap().register(key, factory);
}

/// 全局注册单例
pub fn register_singleton<F, T>(key: &str, factory: F)
where
    F: Fn() -> T + Send + Sync + 'static,
    T: Any + Send + Sync + 'static,
{
    global().write().unwrap().register_singleton(key, factory);
}

/// 全局获取多例
pub fn get<T: Any + Clone>(key: &str) -> Option<T> {
    global().read().unwrap().get(key)
}

/// 全局获取单例(Arc<T>)
pub fn get_singleton<T: Any + Send + Sync>(key: &str) -> Option<Arc<T>> {
    global().read().unwrap().get_singleton(key)
}

// ==================== 使用示例 ====================

#[derive(Debug)]
struct Database {
    id: u64,
}

impl Database {
    fn new() -> Self {
        println!(">>> Database::new() 执行");
        Self { id: rand::random() }
    }
}

#[derive(Debug,Clone)]
struct Logger;

impl Logger {
    fn new() -> Self {
        println!(">>> Logger::new() 执行");
        Self
    }
}

#[test]
fn test01_container() {
    // 1. 注册(全局,任意地方都能调)
    register_singleton("db", Database::new);
    register("logger", Logger::new);

    // 2. 获取单例(首次 get 时才 new,之后复用)
    let db1 = get_singleton::<Database>("db").unwrap();
    let db2 = get_singleton::<Database>("db").unwrap();
    println!("Arc::ptr_eq(db1, db2) = {}", Arc::ptr_eq(&db1, &db2)); // true

    // 3. 获取多例(每次 get 都 new)
    let log1 = get::<Logger>("logger").unwrap();
    let log2 = get::<Logger>("logger").unwrap();
    println!("多例: log1={:?}, log2={:?}  ", log1, log2 );
}
pub fn get_db() -> Option<Arc<Database>> {
    get_singleton::<Database>("db")
}
#[test]
fn test_02_log() {
    let cli=database::find_bean_redis_client()
        .unwrap();
       let v= cli.set_key("my_key", "1111");
    println!("{:?}", v.unwrap());
    let v = cli.get_key("my_key");
        println!("{:?}", v.unwrap());
    let v = cli.del_key("my_key");

}