应用模型
Boot 把应用视为一张由 Module 组织的类型化 Provider 图。Module 决定边界和可见性,Provider 决定实例如何构造,Controller、Gateway 与消息模式消费这些实例。
Module 是边界
一个 Module 可以声明:
- 普通导入与显式 forward import
- Provider 及其导出 token
- HTTP Controller 与直接路由
- WebSocket Gateway 与消息模式
- module route prefix 和 middleware
- 初始化、bootstrap 与 shutdown hook
属性宏适合静态模块:
导出只让 importing module 看见 Provider。把模块标记为 global 会让导出对所有模块可见,但会弱化依赖来源,适合配置、日志等真正跨应用能力,不适合普通业务服务。
Provider 定义
ProviderDefinition 支持以下构造方式:
#[injectable] 支持命名字段中的 Arc<T>、Option<Arc<T>>、ProviderRef<T> 与 Option<ProviderRef<T>>。#[inject("token")] 把字段切换到命名 token。
缺失的必需 token 和非法环会返回带上下文的 BootError。可选依赖只在 token 不可见时得到 None,不会吞掉 Provider factory 自身的构造错误。
生命周期 scope
如果 singleton 的 eager 依赖是 request-scoped,该依赖链会自动向上冒泡到 request scope。ProviderRef<T> 是 lazy edge,不参与 scope 冒泡;调用方必须使用捕获的请求 context 或显式 resolve(...)。
ContextIdFactory 可以创建新上下文,也可以让多个解析共享同一个上下文。HTTP、WebSocket 与 transport dispatcher 会为每次调用建立对应上下文。
动态与延迟模块
DynamicModule 用于由配置决定的导入、Provider、导出、Controller、Gateway 与消息模式。它仍然遵守普通 Module 的可见性规则。
LazyModuleLoader 可以在启动后加载隔离的 Provider 功能模块。应用级 Guard、Pipe、Interceptor 与 Filter 必须 eager import,因为 handler 在构建阶段已经编译,延迟加入全局增强器会让执行拓扑不一致。
模块循环关系必须通过 forward import 明确声明。Provider 循环应优先重新划分职责;确有延迟解析需求时使用 ProviderRef<T>,不要关闭正常的 cycle 诊断。
Factory 与生命周期
BootFactory 根据进程角色选择外壳:
Module 和 singleton Provider 可以观察以下阶段:
使用 shutdown-hooks 时,SIGINT 与 SIGTERM 的标签会传给支持 signal 的 shutdown hook。所有外部资源都应在 hook 中显式关闭,不能依赖进程退出自动丢弃。
图检查建议
- 让业务 Module 只导出被其他边界真实消费的 token。
- 让 Controller 只编排输入、应用服务和输出。
- 使用 named token 表达同类型的不同 backend,不用字符串选项在运行时分支。
- 把连接池和客户端作为 Provider 注入,不在 injectable class 内直接
new。 - 通过
DiscoveryService或ApplicationGraph检查模块、Provider、路由、Gateway 与消息模式快照。
下一步阅读Controller 与路由或请求管线。