tx-di-macros
proc-macro crate,为 tx-di-core DI 框架提供 #[derive(Component)] 宏。
模块结构
tx-di-macros/src/
├── lib.rs # proc_macro 入口 + 文档
├── attr/
│ ├── mod.rs # re-export
│ ├── comp_attr.rs # #[component(...)] 属性解析 + CompAttr / ScopeAttr 定义
│ └── field_attr.rs # #[tx_cst(...)] 字段属性解析
├── classify/
│ ├── mod.rs
│ └── fields.rs # FieldKind 枚举 + classify_fields 函数
├── codegen/
│ ├── mod.rs # CodeGenContext + derive_component_impl 编排
│ ├── component_impl.rs # 生成 impl Component for T(含 intercept init 装配)
│ ├── factory.rs # 生成 factory 闭包
│ ├── inner_init.rs # 生成 inner_init 方法
│ ├── lifecycle.rs # 生命周期覆写(init/app_init/app_async_init/app_async_run/shutdown)
│ ├── intercept.rs # 生成 AOP 拦截器链 init 覆写
│ └── meta_entry.rs # 生成 linkme ComponentMeta 注册条目
├── intercept_macro.rs # #[intercept] 方法属性宏
├── type_utils.rs # 类型检测工具(Arc/Option/Arc<dyn Trait>)
└── name_utils.rs # 命名转换工具(驼峰 ↔ 蛇形)
数据流
属性解析 ──→ 字段分类 ──→ CodeGenContext ──→ 代码生成 ──→ 组装输出
(comp_attr) (fields) (4个子模块) (quote!)
各模块职责
| 模块 | 职责 | 对外 API |
|---|---|---|
attr::comp_attr |
解析 #[component(...)] 为 CompAttr |
parse_component_attr_from_attributes, CompAttr, ScopeAttr |
attr::field_attr |
解析 #[tx_cst(expr)] 和 #[tx_cst(skip)] |
extract_inject_expr, has_skip_attr |
classify::fields |
按类型形态对字段分类 | classify_fields, FieldKind |
codegen |
编排代码生成 + 持有 CodeGenContext |
derive_component(proc_macro 入口) |
codegen::component_impl |
生成 impl Component |
gen_component_impl |
codegen::factory |
生成 factory 闭包 | gen_factory_fn |
codegen::inner_init |
生成 inner_init 方法 |
gen_inner_init |
codegen::lifecycle |
生成生命周期覆写(init / app_init / app_async_init / app_async_run / shutdown) | gen_lifecycle_overrides |
codegen::intercept |
生成 AOP 拦截器链 init 覆写 |
gen_interceptor_init_override |
codegen::meta_entry |
生成 linkme 注册条目 |
gen_meta_entry |
intercept_macro |
提供 #[intercept] 方法属性宏 |
intercept_impl |
type_utils |
类型检测工具函数 | strip_arc_type, is_option_type, is_arc_dyn_trait, is_plain_arc_dyn_trait, extract_trait_from_arc, extract_trait_from_option_arc |
name_utils |
命名转换工具函数 | camel_to_snake, camel_to_screaming_snake |
使用方法
1. 基本使用
use Component;
字段 repo: Arc<UserRepo> 会自动解析为 UserRepo 类型的组件依赖,从容器中注入。
2. 作用域
// 原型作用域:每次注入都创建新实例
默认作用域为 Singleton(单例)。支持 Singleton 和 Prototype 两种。
3. 生命周期回调
每个生命周期都通过一个 #[component(...)] 标志和一个自定义函数实现:
#[component(...)] |
回调函数签名 | 覆写 trait 方法 | 阶段 |
|---|---|---|---|
init |
fn init(&mut self, store: &Store) -> RIE<()> |
inner_init |
build 后 |
app_init |
fn app_init(comp: Arc<Self>, app: &Arc<App>) -> RIE<()> |
init |
同步初始化 |
app_async_init |
fn app_async_init(comp: Arc<Self>, app: &Arc<App>) -> BoxFuture<RIE<()>> |
async_init |
异步初始化 |
app_async_run |
fn app_async_run(comp: Arc<Self>, app: &Arc<App>, token: CancellationToken) -> BoxFuture<RIE<()>> |
async_run |
后台运行 |
shutdown |
fn shutdown(&self) |
shutdown |
优雅关闭 |
use ;
use Arc;
4. 配置组件
5. Trait 实现注册
通过 trait object 按接口注入:
6. 生命周期回调实现示例
回调函数名与 #[component(...)] 标志保持一致(如 init 标志对应 fn init,app_init 对应 fn app_init)。
宏生成的覆写方法使用 self:: 前缀调用回调,即使 init / shutdown 与 trait 方法同名也不会冲突。
// 对应 #[component(init)]:覆写 inner_init,build 完成后、正式使用前调用
注意:这里的
fn init覆写的是inner_init而非 trait 的init/init(app)。shutdown回调则直接用&self作为接收器。
7. 初始化排序
use Component;
// 最小整数 → 最先初始化
默认排序值为 10000。值越小越先执行。通常核心基础设施使用负值。
7. 字段级自定义
8. 依赖注入规则总结
| 字段类型 | 注入行为 |
|---|---|
Arc<T> |
普通组件注入,从容器获取 T |
Arc<dyn Trait> |
必选 trait 注入,inner_init 中填充 |
Option<Arc<dyn Trait>> |
可选 trait 注入,找不到时保持 None |
Option<T> |
可选普通依赖,保持 None |
#[tx_cst(expr)] |
表达式赋值 |
#[tx_cst(skip)] |
跳过,使用 Default::default() |
开发指南
添加新的 #[component(...)] 参数
- 在
attr/comp_attr.rs的CompAttr结构体添加字段 - 在
CompAttrArgs添加对应字段 - 在
parse()方法中添加解析分支 - 在
codegen/相应子模块中使用新字段生成代码
添加新的字段注入类型
- 在
classify/fields.rs的FieldKind添加变体 - 在
classify_fields()中添加匹配规则 - 在
codegen/component_impl.rs的build_fields映射中添加处理 - 如有需要,在
codegen/inner_init.rs或codegen/meta_entry.rs中添加相应处理
测试
# 运行全部测试
# 仅编译宏(快速检查)
核心测试位于 tx-di-core/tests/test_component.rs,覆盖宏的各条代码生成路径。