概念
框架基础概念中英文对照
中文 | 英文 | 描述 |
---|
结构 | Struct | Go 语言的 struct 类型结构体 |
对象 | Object | Go 语言中的实例化对象 |
接口 | Interface | Go 语言中的 interface 类型接口 |
方法 | Method | Go 语言中的接口、对象大写字母开头的函数方法 |
依赖注入 | Dependency Injection(DI) | |
自动装载 | Auto Wire | |
结构描述符 | Struct Descriptor (SD) | |
结构描述键 | Struct Descriptor Identification(SDID) | 自动装载模型内索引结构的唯一ID。 |
1 - 依赖注入
概念
依赖注入(Dependency Injection)是指开发人员无需显式地创建对象,而是通过标签的方式声明字段,由框架负责将实例化对象写入该字段。
优点
依赖注入可以降低代码的耦合度,减少冗余代码量,优化代码逻辑。帮助开发人员面向对象编程,面向接口编程。
IOC-golang 的依赖注入能力
本框架从两个角度实现依赖注入:
2 - 自动装载模型
概念
自动装载(Autowire)模型封装了一类对象的装载方式,是本框架对装载过程抽象出的概念和接口。
用户需要定义的结构千变万化,如果每个结构描述符都要提供完整的装载过程信息,将是一件很麻烦的事情。我们可以将一类相似的结构抽象出一个自动装载模型,选择注册在该模型的所有对象都需要遵循该模型的加载策略,这大大降低了用户提供的结构描述符数据量,提高开发效率。
框架内置了两个基础自动装载模型:单例模型(singleton),多例模型(normal)
框架提供了两个扩展的自动装载模型:配置(config),gRPC 客户端(grpc)。其中配置模型是多例模型的扩展,gRPC 客户端是单例模型的扩展。框架内置了基于“配置自动装载模型”的多个结构。例如,用户可以用几行代码将 “gRPC 客户端存根”注册在 “grpc 装载模型” 之上【示例】,方便地从配置文件中的指定位置读入下游主机名、从标签读入客户端名称,注入客户端单例指针。
3 - 结构描述符
概念
结构描述符(Struct Descriptor, SD)用于描述一个被开发者定义的结构,包含对象生命周期的全部信息,例如结构类型是什么,实现了哪些接口,如何被构造等等。
SD可以通过注解的方式使用工具自动生成。但还是推荐开发人员了解本框架定义的结构生命周期和结构描述信息,以便更清晰地开发应用。
对象生命周期
开发人员在 Go 语言开发过程中需要时时关注对象的生命周期,一个常见的对象生命周期如下:
- 对象定义:开发人员编码,编写结构,实现接口,确定模型(单例、多例..) 。
- 加载全部依赖:依赖的下游对象创建、配置读入等。
- 对象创建:产生一个基于该对象的指针
- 对象构造:获取全部依赖,并将其组装到空对象中,产生可用对象。
- 对象使用:调用对象的方法,读写对象字段。
- 对象销毁:销毁对象,销毁无需再使用的依赖对象。
参数
本框架的“参数”概念,是一个结构体,该结构体包含了创建一个对象所需全部依赖,并提供了构造方法。
例如
type Config struct {
Host string
Port string
Username string
Password string
}
func (c *Config) New(mysqlImpl *Impl) (*Impl, error) {
var err error
mysqlImpl.db, err = gorm.Open(mysql.Open(getMysqlLinkStr(c)), &gorm.Config{})
mysqlImpl.tableName = c.TableName
return mysqlImpl, err
}
Config 结构即为 Impl 结构的“参数”。其包含了产生 Impl 结构的全部信息。
结构描述符 (Struct Descriptor)
本框架定义的结构描述符如下:
type StructDescriptor struct {
Factory func() interface{}
ParamFactory func() interface{}
ParamLoader ParamLoader
ConstructFunc func(impl interface{}, param interface{}) (interface{}, error)
DestroyFunc func(impl interface{})
autowireType string
}
Factory【必要】
结构的工厂函数,返回值是未经初始化的空结构指针,例如
func () interface{}{
return &App{}
}
ParamFactory【非必要】
参数的工厂函数,返回值是未经初始化的空参数指针,例如
func () interface{}{
return &Config{}
}
ParamLoader【非必要】
参数加载器定义了参数的各个字段如何被加载,是从注入标签传入、还是从配置读入、或是以一些定制化的方式。
框架提供了默认的参数加载器,详情参阅 参数加载器概念
Constructor【非必要】
构造函数定义了对象被组装的过程。
入参为对象指针和参数指针,其中对象指针的所有依赖标签都已被注入下游对象,可以在构造函数中调用下游对象。参数指针的所有字段都已经按照参数加载器的要求加载好。构造函数只负责拼装。
返回值为经过拼装后的指针。例如:
func(i interface{}, p interface{}) (interface{}, error) {
param := p.(*Config)
impl := i.(*Impl)
return param.New(impl)
},
DestroyFunc 【非必要】
定义了对象的销毁过程,入参为对象指针。
autowireType 【必要】
定义了对象的自动装载模型,例如单例模型、多例模型等,详情参阅 自动装载模型概念
结构描述ID
结构描述ID定义为:"$(包名).$(结构名)"
结构描述 ID (Struct Description Identification) 在本文档和项目中多处被缩写为 SDID。
SDID 是唯一的,用于索引结构的键,类型为字符串。
开发人员在使用 API 的方式从自动装载模型获取对象时,需要传入SDID来获取。
4 - 参数加载器
概念
参数加载器描述了依赖参数如何在对象构造之前被加载,包括但不限于从配置加载、从标签参数加载等等。
参数加载器作为 SD(结构描述符)的一部分,可以被结构提供方定制化,也可以使用自动装载模型提供的默认参数加载器。
默认参数加载器
任何 SD 内定义参数加载器均被优先执行,如果加载失败,则尝试使用默认参数加载器加载。
默认参数加载器被两个基础自动装载模型(singleton、normal)引入。依此采用三种方式加载参数,如果三种方式均加载失败,则抛出错误。
方式1 从标签指向的对象名加载参数,参考 配置文件结构规范
Load support load struct described like:
```go
normal.RegisterStructDescriptor(&autowire.StructDescriptor{
Factory: func() interface{}{
return &Impl{}
},
ParamFactory: func() interface{}{
return &Config{}
},
ConstructFunc: func(i interface{}, p interface{}) (interface{}, error) {
return i, nil
},
})
}
type Config struct {
Address string
Password string
DB string
}
```
with
Autowire type 'normal'
StructName 'Impl'
Field:
MyRedis Redis `normal:"github.com/alibaba/ioc-golang/extension/normal/redis.Impl, redis-1"`
from:
```yaml
extension:
normal:
github.com/alibaba/ioc-golang/extension/normal/redis.Impl:
redis-1:
param:
address: 127.0.0.1
password: xxx
db: 0
方式2 从标签加载参数
Load support load param like:
```go
type Config struct {
Address string
Password string
DB string
}
```
from field:
```go
NormalRedis normalRedis.Redis `normal:"github.com/alibaba/ioc-golang/extension/normal/redis.Impl,address=127.0.0.1&password=xxx&db=0"`
```
方式3 从配置加载参数,参考 配置文件结构规范
Load support load struct described like:
```go
normal.RegisterStructDescriptor(&autowire.StructDescriptor{
Factory: func() interface{}{
return &Impl{}
},
ParamFactory: func() interface{}{
return &Config{}
},
ConstructFunc: func(i interface{}, p interface{}) (interface{}, error) {
return i, nil
},
})
}
type Config struct {
Address string
Password string
DB string
}
```
with
Autowire type 'normal'
StructName 'Impl'
from:
```yaml
autowire:
normal:
github.com/alibaba/ioc-golang/extension/normal/redis.Impl:
param:
address: 127.0.0.1
password: xxx
db: 0
5 - 注解
概念
注解(annotation) 是 Go 代码中符合特定格式的注释,一般位于结构定义之前。可被命令行工具扫描,从而获取结构信息,自动生成需要的代码。
例如快速开始示例中的
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
...
}
注解在 Go 应用开发的过程中,是一种直观、清晰的结构描述方式,通过使用注解进行标注,使用工具自动生成相关代码,可减少开发人员的工作量,降低代码重复率。
注解与代码生成
注解与代码生成能力,是为了让开发者无需关心SD(结构描述符)的组装和注册。开发者只需定义好结构,正确标注注解,即可使用 iocli 工具自动生成当前目录和子目录下的 SD 。
iocli 工具支持的注解
详情参阅 iocli #结构注解