Skip to main content

Wire 依赖注入

Wire 是一个灵活的依赖注入工具,通过自动生成代码的方式在编译期完成依赖注入。

在各个组件之间的依赖关系中,通常鼓励显式初始化,而不是全局变量传递。

所以通过 Wire 进行初始化代码,可以很好地解决组件之间的耦合,以及提高代码维护性。

安装工具#

go get github.com/google/wire/cmd/wire

工作原理#

Wire 具有两个基本概念:ProviderInjector

Provider 是一个普通的 Go Func ,这个方法也可以接收其它 Provider 的返回值,从而形成了依赖注入;

// 提供一个配置文件(也可能是配置文件)func NewConfig() *conf.Data {...}
// 提供数据组件,依赖了数据配置(初始化 Database、Cache 等)func NewData(c *conf.Data) (*Data, error) {...}
// 提供持久化组件,依赖数据组件(实现 CURD 持久化层)func NewUserRepo(d *data.Data) (*UserRepo, error) {...}

使用方式#

在 Kratos 中,主要分为 server、service、biz、data 服务模块,会通过 Wire 进行模块顺序的初始化;

kratos ddd

在每个模块中,只需要一个 ProviderSet 提供者集合,就可以在 wire 中进行依赖注入;

并且我们在每个组件提供入口即可,不需要其它依赖,例如:

-data--data.go    // var ProviderSet = wire.NewSet(NewData, NewGreeterRepo)--greeter.go // func NewGreeterRepo(data *Data, logger log.Logger) biz.GreeterRepo {...}

然后通过 wire.go 中定义所有 ProviderSet 可以完成依赖注入配置。

初始化组件#

通过 wire 初始化组件,需要定义对应的 wire.go,以及 kratos application 用于启动管理。

// 应用程序入口cmd-main.go-wire.go-wire_gen.go
// main.go 创建 kratos 应用生命周期管理func newApp(logger log.Logger, hs *http.Server, gs *grpc.Server, greeter *service.GreeterService) *kratos.App {    pb.RegisterGreeterServer(gs, greeter)    pb.RegisterGreeterHTTPServer(hs, greeter)    return kratos.New(        kratos.Name(Name),        kratos.Version(Version),        kratos.Logger(logger),        kratos.Server(            hs,            gs,        ),    )}
// wire.go 初始化模块func initApp(*conf.Server, *conf.Data, log.Logger) (*kratos.App, error) {    // 构建所有模块中的 ProviderSet,用于生成 wire_gen.go 自动依赖注入文件    panic(wire.Build(server.ProviderSet, data.ProviderSet, biz.ProviderSet, service.ProviderSet, newApp))}

在项目的 main 目录中,运行 go generate 进行生成编译期依赖注入代码:

go generate ./...

References#