Skip to main content

tx_di_core/
aop.rs

1//! AOP 拦截器 — 横切关注点分离
2//!
3//! 拦截器通过 DI 框架管理:拦截器本身也是 `#[derive(Component)]`,
4//! 可依赖其他服务。通过 `#[component(intercept(InterceptorType))]` 显式声明
5//! 需要哪些拦截器,框架在 App 阶段从 Store 中精确注入。
6//!
7//! # 使用方式
8//!
9//! ```ignore
10//! // 1. 定义拦截器(也是 DI 组件)
11//! #[derive(Component)]
12//! pub struct AuthInterceptor {
13//!     pub session: Arc<SessionService>,   // DI 自动注入
14//! }
15//! impl Interceptor for AuthInterceptor {
16//!     fn before(&self, ctx: &CallContext) -> RIE<()> {
17//!         tracing::info!("参数: {:?}", ctx.args);
18//!         Ok(())
19//!     }
20//!     fn after(&self, ctx: &CallContext, result: &mut CallResult) {
21//!         match result {
22//!             CallResult::Ok => tracing::info!("成功"),
23//!             CallResult::Err(e) => tracing::warn!("失败: {}", e),
24//!         }
25//!     }
26//! }
27//!
28//! // 2. 业务组件声明需要哪些拦截器
29//! #[derive(Component)]
30//! #[component(intercept(AuthInterceptor, AuditInterceptor))]
31//! pub struct UserService;
32//!
33//! impl UserService {
34//!     #[intercept]
35//!     pub fn get_user(&self, user_id: u64) -> RIE<User> {
36//!         // 业务逻辑
37//!     }
38//! }
39//! ```
40
41use std::sync::Arc;
42use std::sync::atomic::{AtomicU64, Ordering};
43
44use crate::component::Component;
45use crate::RIE;
46
47// ── CallContext ─────────────────────────────────────────────────────────────
48
49/// 调用上下文 — 传递给拦截器的上下文信息
50pub struct CallContext {
51    /// 方法名
52    pub method_name: &'static str,
53    /// 参数 Debug 表示(用于日志/监控拦截器)
54    pub args: Vec<ArgValue>,
55}
56
57impl CallContext {
58    /// 创建新的调用上下文
59    pub fn new(method_name: &'static str) -> Self {
60        CallContext {
61            method_name,
62            args: Vec::new(),
63        }
64    }
65    /// 添加参数(Debug 表示)
66    pub fn with_arg(mut self, arg: ArgValue) -> Self {
67        self.args.push(arg);
68        self
69    }
70}
71
72// ── ArgValue ────────────────────────────────────────────────────────────────
73
74/// 参数值(用于日志和调试)
75#[derive(Debug, Clone)]
76pub enum ArgValue {
77    I64(i64),
78    Str(String),
79    Bool(bool),
80    Other(String),
81}
82
83impl From<i64> for ArgValue {
84    fn from(v: i64) -> Self { ArgValue::I64(v) }
85}
86impl From<&str> for ArgValue {
87    fn from(v: &str) -> Self { ArgValue::Str(v.to_string()) }
88}
89impl From<String> for ArgValue {
90    fn from(v: String) -> Self { ArgValue::Str(v) }
91}
92impl From<bool> for ArgValue {
93    fn from(v: bool) -> Self { ArgValue::Bool(v) }
94}
95
96// ── CallResult ──────────────────────────────────────────────────────────────
97
98/// 调用结果(`after` 可修改此值以加工返回描述)
99#[derive(Debug)]
100pub enum CallResult {
101    Ok,
102    Err(String),
103}
104
105// ── Interceptor trait ───────────────────────────────────────────────────────
106
107/// AOP 拦截器 trait
108///
109/// - `before`:只读上下文,返回 `Err` 阻止方法执行
110/// - `after`:可修改 `CallResult` 以加工返回描述(日志/监控用)
111pub trait Interceptor: Send + Sync + 'static {
112    #[allow(unused_variables)]
113    fn before(&self, ctx: &CallContext) -> RIE<()> { Ok(()) }
114    #[allow(unused_variables)]
115    fn after(&self, ctx: &CallContext, result: &mut CallResult) {}
116}
117
118// ── InterceptorChain ────────────────────────────────────────────────────────
119
120/// 拦截器链 — 按顺序执行多个拦截器(非泛型,支持异构拦截器混合)
121pub struct InterceptorChain {
122    interceptors: Vec<Arc<dyn Interceptor>>,
123}
124
125impl InterceptorChain {
126    pub fn new() -> Self {
127        InterceptorChain { interceptors: Vec::new() }
128    }
129    /// 添加拦截器(按值,自动 `Arc<dyn Interceptor>`)
130    pub fn push<I: Interceptor>(&mut self, interceptor: I) {
131        self.interceptors.push(Arc::new(interceptor));
132    }
133    /// 添加已 `Arc` 包装的拦截器
134    pub fn push_arc(&mut self, interceptor: Arc<dyn Interceptor>) {
135        self.interceptors.push(interceptor);
136    }
137    /// before_all — 顺序执行,任一 Err 即停止
138    pub fn before_all(&self, ctx: &CallContext) -> RIE<()> {
139        for interceptor in &self.interceptors {
140            interceptor.before(ctx)?;
141        }
142        Ok(())
143    }
144    /// after_all — 逆序执行,可传递可变 `CallResult` 让拦截器加工
145    pub fn after_all(&self, ctx: &CallContext, result: &mut CallResult) {
146        for interceptor in self.interceptors.iter().rev() {
147            interceptor.after(ctx, result);
148        }
149    }
150}
151impl Default for InterceptorChain { fn default() -> Self { Self::new() } }
152
153// ── 内置拦截器 ──────────────────────────────────────────────────────────────
154
155/// 日志拦截器
156pub struct LoggingInterceptor;
157
158impl Component for LoggingInterceptor {
159    type Deps = ();
160    fn build(_: Self::Deps) -> Self { LoggingInterceptor }
161    const SCOPE: crate::Scope = crate::Scope::Singleton;
162}
163impl Default for LoggingInterceptor { fn default() -> Self { LoggingInterceptor } }
164impl Interceptor for LoggingInterceptor {
165    fn before(&self, ctx: &CallContext) -> RIE<()> {
166        tracing::info!("→ {} {:?}", ctx.method_name, ctx.args);
167        Ok(())
168    }
169    fn after(&self, ctx: &CallContext, result: &mut CallResult) {
170        match result {
171            CallResult::Ok => tracing::info!("← {} OK", ctx.method_name),
172            CallResult::Err(e) => tracing::warn!("← {} ERR: {}", ctx.method_name, e),
173        }
174    }
175}
176
177/// 指标拦截器
178pub struct MetricsInterceptor { pub counter: AtomicU64 }
179
180impl Component for MetricsInterceptor {
181    type Deps = ();
182    fn build(_: Self::Deps) -> Self { MetricsInterceptor { counter: AtomicU64::new(0) } }
183    const SCOPE: crate::Scope = crate::Scope::Singleton;
184}
185impl MetricsInterceptor {
186    pub fn new() -> Self { MetricsInterceptor { counter: AtomicU64::new(0) } }
187    pub fn count(&self) -> u64 { self.counter.load(Ordering::Relaxed) }
188}
189impl Default for MetricsInterceptor { fn default() -> Self { Self::new() } }
190impl Interceptor for MetricsInterceptor {
191    fn before(&self, _ctx: &CallContext) -> RIE<()> {
192        self.counter.fetch_add(1, Ordering::Relaxed);
193        Ok(())
194    }
195}
196
197// ── 拦截器链存储(per-instance)──────────────────────────────────────────────
198//
199// 拦截器链按「组件实例指针」存储,而非 per-type 全局静态。这样同进程内多个
200// App(如并行运行的测试)各自持有独立组件实例,其拦截链互不干扰,不会出现
201// 某一 App 的 init 覆盖另一 App 拦截链的竞态问题。
202//
203// key = `Arc<Self>` 的内部指针(`Arc::as_ptr` 与 `&self as *const Self` 一致)。
204
205use std::collections::HashMap;
206use std::sync::Mutex;
207use std::sync::OnceLock;
208
209static INTERCEPTOR_CHAINS: OnceLock<Mutex<HashMap<usize, Arc<InterceptorChain>>>> =
210    OnceLock::new();
211
212fn chains_map() -> &'static Mutex<HashMap<usize, Arc<InterceptorChain>>> {
213    INTERCEPTOR_CHAINS.get_or_init(|| Mutex::new(HashMap::new()))
214}
215
216/// 按组件实例指针设置拦截器链(由 `#[component(intercept(...))]` 生成的 `init` 调用)
217pub fn set_interceptor_chain(key: usize, chain: Arc<InterceptorChain>) {
218    chains_map().lock().unwrap().insert(key, chain);
219}
220
221/// 按组件实例指针获取拦截器链(由 `#[intercept]` 方法调用)
222pub fn get_interceptor_chain(key: usize) -> Option<Arc<InterceptorChain>> {
223    chains_map().lock().unwrap().get(&key).cloned()
224}