wire与依赖注入
Wire 是一个的Golang依赖注入工具,通过自动生成代码的方式在编译期完成依赖注入,Java体系中最出名的Spring框架采用运行时注入,个人认为这是wire和其他依赖注入最大的不同之处。
依赖注入(Dependency Injection)也称作控制反转(Inversion of Control),个人给控制反转下的定义如下:
当前对象需要的依赖对象由外部提供(通常是IoC容器),外部负责依赖对象的构造等操作,当前对象只负责调用,而不关心依赖对象的构造。即依赖对象的控制权交给了IoC容器。
下面给出一个控制反转的示例,比如我们通过配置去创建一个数据库连接:
// 连接配置
type DatabaseConfig struct {
Dsn string
}
func NewDB(config *DatabaseConfig)(*sql.DB, error) {
db,err := sql.Open(“mysql”, config.Dsn)
if err != nil {
return nil, err
}
// …
}
fun NewConfig()(*DatabaseConfig,error) {
// 读取配置文件
fp, err := os.Open(“config.json”)
if err != nil {
return nil,err
}
defer fp.Close()
// 解析为Json
var config DatabaseConfig
if err:=json.NewDecoder(fp).Decode(&config);err!=nil {
return nil,err
}
return &config, nil
}
func InitDatabase() {
cfg, err:=NewConfig()
if err!=nil {
log.Fatal(err)
}
db,err:=NewDB(cfg)
if err!=nil {
log.Fatail(err)
}
// db对象构造完毕
}
数据库配置怎么来的,NewDB方法并不关心(示例代码采用的是NewConfig提供的JSON配置对象),NewDB只负责创建DB对象并返回,和配置方式并没有耦合,所以即使换成配置中心或者其他方式来提供配置,NewDB代码也无需更改,这就是控制反转的魔力!
来看一个反面例子,也就是控制正转:
当前对象需要的依赖由自己创建,即依赖对象的控制权在当前对象自己手里。
type DatabaseConfig struct {
Dsn string
}
func NewDB()(*sql.DB, error) {
// 读取配置文件
fp, err := os.Open(“config.json”)
if err != nil {
return nil,err
}
defer fp.Close()
// 解析为Json
var config DatabaseConfig
if err:=json.NewDecoder(fp).Decode(&config);err!=nil {
return nil,err
}
// 初始化数据库连接
db,err = sql.Open(“mysql”, config.Dsn)
if err != nil {
return
}
// …
}
在控制正转模式下,NewDB方法需要自己实现配置对象的创建工作,在示例中需要读取Json配置文件,这是强耦合的代码,一旦配置文件的格式不是Json&