Wire如何梳理对象依赖关系
目录
Wire通过静态代码分析来梳理对象之间的依赖关系,其核心机制可以概括为以下几个关键点:
1. 依赖图构建
Wire会分析所有Provider函数的输入参数和返回值,自动构建一个类型依赖图:
// Provider示例
func NewA() *A {...} // 提供*A
func NewB(a *A) *B {...} // 需要*A,提供*B
func NewApp(b *B, config *Config) *App {...} // 需要*B和*Config
Wire会识别出:
*Config → *A → *B → *App
2. 依赖解析过程
步骤1:从目标类型出发
从Injector的返回值类型开始逆向解析:
func InitializeApp() (*App, error) {
wire.Build(NewApp, NewB, NewA, LoadConfig)
return nil, nil
}
步骤2:递归查找依赖
- 需要
*App→ 需要NewApp函数 NewApp需要*B和*Config→ 查找提供这些类型的Provider*B需要NewB→NewB需要*A*A需要NewA→NewA无依赖
步骤3:拓扑排序
Wire会将依赖关系排序为:
LoadConfig(提供*Config)NewA(提供*A)NewB(需要*A,提供*B)NewApp(需要*B和*Config)
3. 依赖冲突解决
当同一类型有多个Provider时,Wire会:
- 优先选择显式指定的Provider
- 使用接口绑定解决冲突:
var dbSet = wire.NewSet(NewMySQLDB, wire.Bind(new(DB), new(*MySQLDB)))
- 如果仍有歧义,编译时报错
4. 高级依赖管理
Provider Set
将相关Provider分组:
var repoSet = wire.NewSet(NewUserRepo, NewOrderRepo)
结构体Provider
自动填充结构体字段:
type App struct {
UserRepo *UserRepo
OrderRepo *OrderRepo
}
var appSet = wire.NewSet(
NewApp, // 返回*App
wire.Struct(new(App), "*"), // 自动注入所有字段
repoSet,
)
清理函数
处理需要清理的资源:
func NewFile() (*os.File, func(), error) {
f, err := os.Open("file.txt")
return f, func() { f.Close() }, err
}
5. 错误处理机制
Wire会确保:
- 依赖项按正确顺序初始化
- 如果任何Provider返回错误,后续依赖不会初始化
- 已创建的资源会被正确清理
通过这种静态分析和代码生成的方式,Wire能够在编译时就确定所有对象的创建顺序和依赖关系,避免了运行时依赖注入的性能开销和不确定性。
Do not communicate by sharing memory; instead, share memory by communicating.

浙公网安备 33010602011771号