use std::sync::Arc;
use dashmap::DashMap;
use std::any::Any;
use std::any::type_name;
use std::ops::Deref;
use once_cell::sync::OnceCell;
use std::sync::Mutex;
pub use autowired_derive::*;
pub use beans::Bean;
pub use inventory::submit;
mod beans;
fn component_mutex() -> &'static Mutex<u64> {
static INSTANCE: OnceCell<Mutex<u64>> = OnceCell::new();
INSTANCE.get_or_init(Default::default)
}
fn component_dashmap() -> &'static DashMap<String, Arc<dyn Any + 'static + Send + Sync>> {
static INSTANCE: OnceCell<DashMap<String, Arc<dyn Any + 'static + Send + Sync>>> = OnceCell::new();
INSTANCE.get_or_init(Default::default)
}
fn bean_dashmap() -> &'static DashMap<String, Bean> {
static INSTANCE: OnceCell<DashMap<String, Bean>> = OnceCell::new();
INSTANCE.get_or_init(Default::default)
}
fn get_component<T: Any + Send + Sync>() -> Option<Arc<T>> {
component_dashmap().get(type_name::<T>())
.map(|x| x.value().clone())
.map(|x| x.downcast::<T>().ok())
.flatten()
}
pub fn exist_component<T>() -> bool {
component_dashmap().contains_key(type_name::<T>())
}
pub trait Component: Any + 'static + Send + Sync {
fn new_instance() -> Option<Self> where Self: Sized;
}
pub struct Autowired<T> {
inner: OnceCell<Arc<T>>,
}
impl<T> Autowired<T> {
pub const fn new() -> Self {
Autowired { inner: OnceCell::new() }
}
}
impl<T: Send + Sync + 'static> Deref for Autowired<T> {
type Target = Arc<T>;
fn deref(&self) -> &Self::Target {
self.inner.get_or_init(|| {
if !exist_component::<T>() {
let name = type_name::<T>();
if let Some(bean) = bean_dashmap().get(name) {
if let Some(component) = (bean.provider)(){
register_with_type_name(name.to_owned(), component);
}
}
}
get_component::<T>().unwrap_or_else(||
panic!("[Autowired] not found component {}", type_name::<T>())
)
})
}
}
impl<T> Default for Autowired<T> {
fn default() -> Self {
Autowired::new()
}
}
pub fn register_with<T: Component>(constructor: impl FnOnce() -> Option<Arc<T>>) -> bool {
let name = type_name::<T>();
if let Ok(mut count) = component_mutex().lock() {
if component_dashmap().contains_key(name) {
return false;
}
let component = match constructor() {
None => return false,
Some(c) => c,
};
component_dashmap().insert(name.to_string(), component.clone());
*count += 1;
log::debug!("[Component] register, name={}", name);
}
true
}
pub fn register<T: Component>(component: Arc<T>) -> bool {
register_with(|| Some(component))
}
fn register_with_type_name(type_name: String, component: Arc<dyn Any + 'static + Send + Sync>) -> bool {
let name = &type_name;
if let Ok(mut count) = component_mutex().lock() {
if component_dashmap().contains_key(name) {
return false;
}
component_dashmap().insert(name.to_string(), component.clone());
*count += 1;
log::debug!("[Component] register, name={}", name);
}
true
}
pub fn setup_submitted_beans() {
for bean in inventory::iter::<Bean> {
if !bean.lazy {
if let Some(component) = (bean.provider)(){
register_with_type_name(bean.type_name.clone(), component);
}
}
bean_dashmap().insert(bean.type_name.clone(), bean.clone());
}
}
pub fn list_bean_names() -> Vec<String> {
bean_dashmap().iter().map(|x| x.type_name.clone()).collect()
}