最新示例代码,位于 ioc-golang/example
示例
- 1: 依赖注入
- 1.1: redis 客户端注入
- 1.2: GORM 客户端注入
- 1.3: 通过 API 获取对象
- 2: 接口 AOP 能力
- 3: 扩展 autowire 模型
- 3.1: 配置注入
- 3.2: RPC 能力
- 3.3: gRPC 客户端注入
1 - 依赖注入
1.1 - redis 客户端注入
简介
本示例展示了注入 Redis 客户端能力。
在应用开发过程中,通过 SDK 操作 Redis 是一个常见的诉求。
ioc-golang 框架提供了注入 Redis 连接的能力,开发者可以在配置文件中指定好 Redis 地址、密码、db名等信息,通过标签注入连接,无需手动创建、组装。
注入模型与结构
关键代码
import(
normalMysql "github.com/alibaba/ioc-golang/extension/normal/mysql"
)
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
NormalRedis normalRedis.Redis `normal:"github.com/alibaba/ioc-golang/extension/normal/redis.Impl"`
NormalDB1Redis normalRedis.Redis `normal:"github.com/alibaba/ioc-golang/extension/normal/redis.Impl,db1-redis"`
NormalDB2Redis normalRedis.Redis `normal:"github.com/alibaba/ioc-golang/extension/normal/redis.Impl,db2-redis"`
NormalDB3Redis normalRedis.Redis `normal:"github.com/alibaba/ioc-golang/extension/normal/redis.Impl,address=127.0.0.1:6379&db=3"`
}
被注入字段类型
normalRedis.Redis 接口
标签
开发人员可以为 normalRedis.Redis 类型的字段增加
normal:"Impl,$(configKey),$(tableName)"
标签。从而注入Redis sdk。例子中的
normal:"github.com/alibaba/ioc-golang/extension/normal/redis.Impl"
的意义为,将配置文件内autowire.normal.<github.com/alibaba/ioc-golang/extension/normal/redis.Impl>.param
定义的值作为参数。例子中的
normal:"github.com/alibaba/ioc-golang/extension/normal/redis.Impl,db1-redis"
的意义为,将配置文件内autowire.normal.<github.com/alibaba/ioc-golang/extension/normal/redis.Impl>.db1-redis.param
定义的值作为参数。例子中的
normal:"github.com/alibaba/ioc-golang/extension/normal/redis.Impl,db2-redis"
的意义为,将配置文件内autowire.normal.<github.com/alibaba/ioc-golang/extension/normal/redis.Impl>.db2-redis.param
定义的值作为参数。例子中的
normal:"github.com/alibaba/ioc-golang/extension/normal/redis.Impl,address=127.0.0.1:6379&db=3"
的意义为,使用标签内定义的 key-value 作为参数配置。默认参数加载策略详情请参阅参数加载器
autowire: normal: github.com/alibaba/ioc-golang/extension/normal/redis.Impl: db1-redis: param: address: localhost:6379 db: 1 db2-redis: param: address: localhost:6379 db: 2 param: address: localhost:6379 db: 0
运行示例
例子会注入多个位于127.0.0.1:6379 的Redis 客户端,数据库id分别为 0、1、2、3.
需要确保您本地运行了redis,可通过 docker run -p6379:6379 redis:latest
快速启动一个。
注入后,方可调用该接口提供的方法。可获取裸 Redis 连接,也可以直接使用封装好的 API 操作Redis。
cd example/autowire_redis_client/cmd
go run .
___ ___ ____ ____ _
|_ _| / _ \ / ___| / ___| ___ | | __ _ _ __ __ _
| | | | | | | | _____ | | _ / _ \ | | / _` | | '_ \ / _` |
| | | |_| | | |___ |_____| | |_| | | (_) | | | | (_| | | | | | | (_| |
|___| \___/ \____| \____| \___/ |_| \__,_| |_| |_| \__, |
|___/
Welcome to use ioc-golang!
[Boot] Start to load ioc-golang config
[Config] Load config file from ../conf/ioc_golang.yaml
[Boot] Start to load debug
[Debug] Debug mod is not enabled
[Boot] Start to load autowire
[Autowire Type] Found registered autowire type singleton
[Autowire Struct Descriptor] Found type singleton registered SD main.App
[Autowire Type] Found registered autowire type normal
[Autowire Struct Descriptor] Found type normal registered SD github.com/alibaba/ioc-golang/extension/normal/redis.Impl
client0 get db0
client1 get db1
client2 get db2
client3 get db3
可看到打印出了已经写入四个 redis db 的值。
1.2 - GORM 客户端注入
简介
本示例展示了注入基于 GORM 的数据库客户端能力。
在应用开发过程中,通过 SDK 操作数据库是一个常见的诉求,GORM 是应用较广泛的 Go 数据库 sdk。
ioc-golang 框架提供了注入数据库连接的能力,开发者可以在配置文件中指定好数据库地址、密码信息,通过标签注入连接,无需手动创建、组装 GORM 客户端。
注入模型与结构
关键代码
import(
normalMysql "github.com/alibaba/ioc-golang/extension/normal/mysql"
)
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
MyDataTable normalMysql.Mysql `normal:"github.com/alibaba/ioc-golang/extension/normal.Impl,my-mysql,mydata"`
}
被注入字段类型
normalMysql.Mysql 接口
标签
开发人员可以为 normalMysql.Mysql 类型的字段增加
normal:"github.com/alibaba/ioc-golang/extension/normal.Impl,$(configKey),$(tableName)"
标签。从而注入指定数据库的指定表 sdk。例子中的
normal:"github.com/alibaba/ioc-golang/extension/normal.Impl,my-mysql,mydata"
的意义为,将配置文件内autowire.normal.<github.com/alibaba/ioc-golang/extension/normal/mysql.Impl>.my-mysql.param
定义的值作为参数。autowire: normal: github.com/alibaba/ioc-golang/extension/normal/mysql.Impl: my-mysql: param: host: "127.0.0.1" port: 3306 username: "root" password: "root" dbname: "test"
例子会建立一个位于127.0.0.1:3306 的数据库连接,用户名为root、密码为 root、数据库名为test、表名为mydata。
注入后,方可调用该接口提供的方法,获取裸 gorm 连接,或者直接使用封装好的 API 操作数据表。
type Mysql interface { GetDB() *gorm.DB SelectWhere(queryStr string, result interface{}, args ...interface{}) error Insert(toInsertLines UserDefinedModel) error Delete(toDeleteTarget UserDefinedModel) error First(queryStr string, findTarget UserDefinedModel, args ...interface{}) error Update(queryStr, field string, target interface{}, args ...interface{}) error }
1.3 - 通过 API 获取对象
简介
本示例展示了通过 API 调用的方式获取对象的能力。
在应用开发过程中,部分依赖通过注入的方式预置在字段中,也有一部分依赖是在程序运行过程中动态生成的。常规做法是通过手动拼装结构的方式,或者通过调用构造函数的方式获取对象。
ioc-golang 框架提供了中心化的获取对象 API。
- 该 API 推荐被结构提供者封装,从而提供一个具象的 API 供用户调用。该 API 传入所需配置结构,返回具体的接口。
extension/normal/redis/redis.go
func GetRedis(config *Config) (Redis, error) {
mysqlImpl, err := normal.GetImpl(SDID, config)
if err != nil {
return nil, err
}
return mysqlImpl.(Redis), nil
}
- 如果结构提供者并没有提供上述 API,用户同样也可以直接调用,传入参数并获取对象。
对象获取 API
多例(normal)
autowire/normal/normal.go
func GetImpl(sdID string, param interface{}) (interface{}, error) {}
每次调用多例获取 API,将创建一个新对象。
单例(singleton)
autowire/singleton/singleton.go
func GetImpl(sdID string) (interface{}, error) {}
单例模型全局只拥有一个对象,通过 API 只能获取而不能创建,在框架启动时所有单例模型指针将基于配置/标签创建好。
关键代码
import(
"github.com/alibaba/ioc-golang/autowire/normal"
"github.com/alibaba/ioc-golang/autowire/singleton"
"github.com/alibaba/ioc-golang/extension/normal/redis"
)
func (a *App) Run() {
// 通过 normal 提供的全局 API,传递结构描述 ID 和配置结构,创建多例对象
normalRedis, err := normal.GetImpl("github.com/alibaba/ioc-golang/extension/normal/redis.Impl", &redis.Config{
Address: "localhost:6379",
DB: "0",
})
// 通过 redis 结构提供者定义好的 GetRedis 方法,传递配置结构,创建多例对象
normalRedis2, err := redis.GetRedis(&redis.Config{
Address: "localhost:6379",
DB: "0",
})
...
}
func main() {
if err := ioc.Load(); err != nil {
panic(err)
}
// 通过 singleton 提供的全局 API,传递结构描述 ID 获取单例对象
appInterface, err := singleton.GetImpl("main.App")
if err != nil {
panic(err)
}
app := appInterface.(*App)
app.Run()
}
运行示例
需要确保您本地运行了redis,可通过 docker run -p6379:6379 redis:latest
快速启动一个。
例子会通过 API 获取 App 对象和 redis 对象,并调用 redis 对象提供的方法。
cd example/get_impl_by_api/cmd
go run .
___ ___ ____ ____ _
|_ _| / _ \ / ___| / ___| ___ | | __ _ _ __ __ _
| | | | | | | | _____ | | _ / _ \ | | / _` | | '_ \ / _` |
| | | |_| | | |___ |_____| | |_| | | (_) | | | | (_| | | | | | | (_| |
|___| \___/ \____| \____| \___/ |_| \__,_| |_| |_| \__, |
|___/
Welcome to use ioc-golang!
[Boot] Start to load ioc-golang config
[Config] Load config file from ../conf/ioc_golang.yaml
Load ioc-golang config file failed. open ../conf/ioc_golang.yaml: no such file or directory
The load procedure is continue
[Boot] Start to load debug
[Debug] Debug mod is not enabled
[Boot] Start to load autowire
[Autowire Type] Found registered autowire type normal
[Autowire Struct Descriptor] Found type normal registered SD github.com/alibaba/ioc-golang/extension/normal/redis.Impl
[Autowire Type] Found registered autowire type singleton
[Autowire Struct Descriptor] Found type singleton registered SD main.App
get val = db0
可看到打印出了 redis 中的数据。
2 - 接口 AOP 能力
2.1 - 可视化
简介
本示例展示了从配置文件注入字段的能力。
在应用开发过程中,从配置文件中读入配置是一个常见的诉求。例如读取数据库的账号密码、下游服务的主机名,以及一些业务配置等。
ioc-golang 框架提供了便捷的基于文件注入配置的能力,使开发者无需手动解析配置文件,无需手动组装对象。
注入模型与结构
关键代码:
import (
github.com/alibaba/ioc-golang/extension/config
)
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
DemoConfigString *config.ConfigString `config:",autowire.config.demo-config.string-value"`
DemoConfigInt *config.ConfigInt `config:",autowire.config.demo-config.int-value"`
DemoConfigMap *config.ConfigMap `config:",autowire.config.demo-config.map-value"`
DemoConfigSlice *config.ConfigSlice `config:",autowire.config.demo-config.slice-value"`
}
被注入字段类型
目前支持 ConfigString,ConfigInt,ConfigMap,ConfigSlice 四种类型。
需要以 指针 的形式声明字段类型
标签与注入位置
开发人员可以给结构增加 ``config:
",xxx"
标签, 标注需要注入的值类型,以及该字段位于配置文件的位置。例子中的
config:",autowire.config.demo-config.string-value"
的意义为,将配置文件内
autowire.config.demo-config.string-value
的值注入到该字段。对应配置文件:ioc_golang.yaml 中的字符串 “stringValue”
autowire: config: demo-config: int-value: 123 int64-value: 130117537261158665 float64-value: 0.001 string-value: stringValue map-value: key1: value1 key2: value2 key3: value3 obj: objkey1: objvalue1 objkey2: objvalue2 objkeyslice: objslicevalue slice-value: - sliceValue1 - sliceValue2 - sliceValue3 - sliceValue4
运行示例
cd example/autowire_config/cmd
go run .
___ ___ ____ ____ _
|_ _| / _ \ / ___| / ___| ___ | | __ _ _ __ __ _
| | | | | | | | _____ | | _ / _ \ | | / _` | | '_ \ / _` |
| | | |_| | | |___ |_____| | |_| | | (_) | | | | (_| | | | | | | (_| |
|___| \___/ \____| \____| \___/ |_| \__,_| |_| |_| \__, |
|___/
Welcome to use ioc-golang!
[Boot] Start to load ioc-golang config
[Config] merge config map, depth: [0]
[Boot] Start to load debug
[Debug] Debug mod is not enabled
[Boot] Start to load autowire
[Autowire Type] Found registered autowire type singleton
[Autowire Struct Descriptor] Found type singleton registered SD main.App
[Autowire Type] Found registered autowire type normal
[Autowire Type] Found registered autowire type config
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigInt64
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigInt
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigMap
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigSlice
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigString
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigFloat64
2022/06/06 18:01:22 load config path autowire.config#demo-config#float64-value error = property [autowire config#demo-config#float64-value]'s key config#demo-config#float64-value not found
stringValue
123
map[key1:value1 key2:value2 key3:value3 obj:map[objkey1:objvalue1 objkey2:objvalue2 objkeyslice:objslicevalue]]
[sliceValue1 sliceValue2 sliceValue3 sliceValue4]
130117537261158665
0
stringValue
123
map[key1:value1 key2:value2 key3:value3 obj:map[objkey1:objvalue1 objkey2:objvalue2 objkeyslice:objslicevalue]]
[sliceValue1 sliceValue2 sliceValue3 sliceValue4]
130117537261158665
0
可看到依次打印出了不同结构的注入配置。
2.2 - 事务
简介
本示例展示了从配置文件注入字段的能力。
在应用开发过程中,从配置文件中读入配置是一个常见的诉求。例如读取数据库的账号密码、下游服务的主机名,以及一些业务配置等。
ioc-golang 框架提供了便捷的基于文件注入配置的能力,使开发者无需手动解析配置文件,无需手动组装对象。
注入模型与结构
关键代码:
import (
github.com/alibaba/ioc-golang/extension/config
)
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
DemoConfigString *config.ConfigString `config:",autowire.config.demo-config.string-value"`
DemoConfigInt *config.ConfigInt `config:",autowire.config.demo-config.int-value"`
DemoConfigMap *config.ConfigMap `config:",autowire.config.demo-config.map-value"`
DemoConfigSlice *config.ConfigSlice `config:",autowire.config.demo-config.slice-value"`
}
被注入字段类型
目前支持 ConfigString,ConfigInt,ConfigMap,ConfigSlice 四种类型。
需要以 指针 的形式声明字段类型
标签与注入位置
开发人员可以给结构增加 ``config:
",xxx"
标签, 标注需要注入的值类型,以及该字段位于配置文件的位置。例子中的
config:",autowire.config.demo-config.string-value"
的意义为,将配置文件内
autowire.config.demo-config.string-value
的值注入到该字段。对应配置文件:ioc_golang.yaml 中的字符串 “stringValue”
autowire: config: demo-config: int-value: 123 int64-value: 130117537261158665 float64-value: 0.001 string-value: stringValue map-value: key1: value1 key2: value2 key3: value3 obj: objkey1: objvalue1 objkey2: objvalue2 objkeyslice: objslicevalue slice-value: - sliceValue1 - sliceValue2 - sliceValue3 - sliceValue4
运行示例
cd example/autowire_config/cmd
go run .
___ ___ ____ ____ _
|_ _| / _ \ / ___| / ___| ___ | | __ _ _ __ __ _
| | | | | | | | _____ | | _ / _ \ | | / _` | | '_ \ / _` |
| | | |_| | | |___ |_____| | |_| | | (_) | | | | (_| | | | | | | (_| |
|___| \___/ \____| \____| \___/ |_| \__,_| |_| |_| \__, |
|___/
Welcome to use ioc-golang!
[Boot] Start to load ioc-golang config
[Config] merge config map, depth: [0]
[Boot] Start to load debug
[Debug] Debug mod is not enabled
[Boot] Start to load autowire
[Autowire Type] Found registered autowire type singleton
[Autowire Struct Descriptor] Found type singleton registered SD main.App
[Autowire Type] Found registered autowire type normal
[Autowire Type] Found registered autowire type config
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigInt64
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigInt
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigMap
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigSlice
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigString
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigFloat64
2022/06/06 18:01:22 load config path autowire.config#demo-config#float64-value error = property [autowire config#demo-config#float64-value]'s key config#demo-config#float64-value not found
stringValue
123
map[key1:value1 key2:value2 key3:value3 obj:map[objkey1:objvalue1 objkey2:objvalue2 objkeyslice:objslicevalue]]
[sliceValue1 sliceValue2 sliceValue3 sliceValue4]
130117537261158665
0
stringValue
123
map[key1:value1 key2:value2 key3:value3 obj:map[objkey1:objvalue1 objkey2:objvalue2 objkeyslice:objslicevalue]]
[sliceValue1 sliceValue2 sliceValue3 sliceValue4]
130117537261158665
0
可看到依次打印出了不同结构的注入配置。
3 - 扩展 autowire 模型
3.1 - 配置注入
简介
本示例展示了从配置文件注入字段的能力。
在应用开发过程中,从配置文件中读入配置是一个常见的诉求。例如读取数据库的账号密码、下游服务的主机名,以及一些业务配置等。
ioc-golang 框架提供了便捷的基于文件注入配置的能力,使开发者无需手动解析配置文件,无需手动组装对象。
注入模型与结构
关键代码:
import (
github.com/alibaba/ioc-golang/extension/config
)
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
DemoConfigString *config.ConfigString `config:",autowire.config.demo-config.string-value"`
DemoConfigInt *config.ConfigInt `config:",autowire.config.demo-config.int-value"`
DemoConfigMap *config.ConfigMap `config:",autowire.config.demo-config.map-value"`
DemoConfigSlice *config.ConfigSlice `config:",autowire.config.demo-config.slice-value"`
}
被注入字段类型
目前支持 ConfigString,ConfigInt,ConfigMap,ConfigSlice 四种类型。
需要以 指针 的形式声明字段类型
标签与注入位置
开发人员可以给结构增加 ``config:
",xxx"
标签, 标注需要注入的值类型,以及该字段位于配置文件的位置。例子中的
config:",autowire.config.demo-config.string-value"
的意义为,将配置文件内
autowire.config.demo-config.string-value
的值注入到该字段。对应配置文件:ioc_golang.yaml 中的字符串 “stringValue”
autowire: config: demo-config: int-value: 123 int64-value: 130117537261158665 float64-value: 0.001 string-value: stringValue map-value: key1: value1 key2: value2 key3: value3 obj: objkey1: objvalue1 objkey2: objvalue2 objkeyslice: objslicevalue slice-value: - sliceValue1 - sliceValue2 - sliceValue3 - sliceValue4
运行示例
cd example/autowire_config/cmd
go run .
___ ___ ____ ____ _
|_ _| / _ \ / ___| / ___| ___ | | __ _ _ __ __ _
| | | | | | | | _____ | | _ / _ \ | | / _` | | '_ \ / _` |
| | | |_| | | |___ |_____| | |_| | | (_) | | | | (_| | | | | | | (_| |
|___| \___/ \____| \____| \___/ |_| \__,_| |_| |_| \__, |
|___/
Welcome to use ioc-golang!
[Boot] Start to load ioc-golang config
[Config] merge config map, depth: [0]
[Boot] Start to load debug
[Debug] Debug mod is not enabled
[Boot] Start to load autowire
[Autowire Type] Found registered autowire type singleton
[Autowire Struct Descriptor] Found type singleton registered SD main.App
[Autowire Type] Found registered autowire type normal
[Autowire Type] Found registered autowire type config
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigInt64
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigInt
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigMap
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigSlice
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigString
[Autowire Struct Descriptor] Found type config registered SD github.com/alibaba/ioc-golang/extension/config.ConfigFloat64
2022/06/06 18:01:22 load config path autowire.config#demo-config#float64-value error = property [autowire config#demo-config#float64-value]'s key config#demo-config#float64-value not found
stringValue
123
map[key1:value1 key2:value2 key3:value3 obj:map[objkey1:objvalue1 objkey2:objvalue2 objkeyslice:objslicevalue]]
[sliceValue1 sliceValue2 sliceValue3 sliceValue4]
130117537261158665
0
stringValue
123
map[key1:value1 key2:value2 key3:value3 obj:map[objkey1:objvalue1 objkey2:objvalue2 objkeyslice:objslicevalue]]
[sliceValue1 sliceValue2 sliceValue3 sliceValue4]
130117537261158665
0
可看到依次打印出了不同结构的注入配置。
3.2 - RPC 能力
使用 RPC 能力
简介
本示例展示了基于 IOC-golang 框架的 RPC 能力
在微服务开发过程中,暴露一些对象的方法给外部程序调用是一种常见的场景。
在 IOC-golang 的 RPC 能力的使用场景下,客户端可以直接注入下游接口的客户端存根,以方法调用的形式发起RPC请求。
关键代码
服务端
需要暴露的RPC服务结构使用 // +ioc:autowire:type=rpc
标注,例如 service.go:
import (
"github.com/alibaba/ioc-golang/example/autowire_rpc/server/pkg/dto"
)
// +ioc:autowire=true
// +ioc:autowire:type=rpc
type ServiceStruct struct {
}
func (s *ServiceStruct) GetUser(name string, age int) (*dto.User, error) {
return &dto.User{
Id: 1,
Name: name,
Age: age,
}, nil
}
使用 iocli 工具生成相关代码。
sudo iocli gen
% tree
.
├── api
│ └── zz_generated.ioc_rpc_client_servicestruct.go
├── service.go
└── zz_generated.ioc.go
会在当前文件目录下生成 zz_generated.ioc.go
包含了服务提供者的结构描述信息。也会在当前目录下创建 api/ 文件夹,并创建当前结构的客户端存根文件 zz_generated.ioc_rpc_client_servicestruct.go
客户端
可以通过标签注入的方法,注入客户端存根,存根中给出下游地址。默认服务暴露端口为2022
import(
"github.com/alibaba/ioc-golang/example/autowire_rpc/server/pkg/service/api"
)
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
ServiceStruct *api.ServiceStructIOCRPCClient `rpc-client:",address=127.0.0.1:2022"`
}
func (a *App) Run() {
for {
time.Sleep(time.Second * 3)
usr, err := a.ServiceStruct.GetUser("laurence", 23) // RPC调用
if err != nil {
panic(err)
}
fmt.Printf("get user = %+v\n", usr)
}
}
运行示例
启动服务端
服务端需要确保引入对应服务提供者结构包: _ "github.com/alibaba/ioc-golang/example/autowire_rpc/server/pkg/service"
package main
import (
"github.com/alibaba/ioc-golang"
_ "github.com/alibaba/ioc-golang/example/autowire_rpc/server/pkg/service"
)
func main() {
// start
if err := ioc.Load(); err != nil {
panic(err)
}
select {}
}
启动服务端进程,默认 rpc 服务监听 2022 端口
% cd server
% go run .
...
[negroni] listening on :2022
启动客户端
开启另一个终端,进入client目录,启动进程,不断发起调用,获得返回值。
% cd client
% go run .
...
get user = &{Id:1 Name:laurence Age:23}
get user = &{Id:1 Name:laurence Age:23}
get user = &{Id:1 Name:laurence Age:23}
3.3 - gRPC 客户端注入
简介
本示例展示了基于 ioc-golang 框架的 gRPC 客户端注入能力。
在进行微服务开发过程中,服务间通信尤为重要,gRPC 是被应用最为广泛的 RPC 框架之一。
在常规开发中,开发者需要从配置中手动读取下游主机名,启动 grpc 客户端。针对一个接口的网络客户端往往是单例模型,如果多个服务都需要使用同一客户端,则还需要开发者维护这个单例模型。
基于 ioc-golang 框架的 gRPC 客户端注入能力,我们可以将客户端的生命周期交付给框架管理,并赋予客户端调试能力,开发者只需要关注注册和使用。
示例介绍
本示例实现了以下拓扑
在这个例子中,App 结构会依此调用所有依赖对象,进而调用一个单例模型注入的 gRPC 客户端,该客户端发起网络请求,并获得结果。
依赖注入模型
关键代码
import(
"github.com/alibaba/ioc-golang/extension/autowire/grpc"
googleGRPC "google.golang.org/grpc"
)
func init() {
// register grpc client
grpc.RegisterStructDescriptor(&autowire.StructDescriptor{
Interface: new(api.HelloServiceClient),
Factory: func() interface{} {
return new(api.HelloServiceClient)
},
ParamFactory: func() interface{} {
return &googleGRPC.ClientConn{}
},
ConstructFunc: func(impl interface{}, param interface{}) (interface{}, error) {
conn := param.(*googleGRPC.ClientConn)
fmt.Println("create conn target ", conn.Target())
return api.NewHelloServiceClient(conn), nil
},
})
}
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
HelloServiceClient api.HelloServiceClient `grpc:"hello-service"`
}
需要在代码中手动注册 gRPC 客户端。在需要使用的地方,增加 grpc:"xxx"
标签
框架会默认从 autowire.grpc.xxx 读取参数, 在例子中,为autowire.grpc.hello-service
autowire:
grpc:
hello-service:
address: localhost:8080
运行示例
启动 grpc Server
% cd example/denbug/grpc_server % go run .
新开一个终端,启动客户端。
% cd example/autowire_grpc_client/cmd % go run . ___ ___ ____ ____ _ |_ _| / _ \ / ___| / ___| ___ | | __ _ _ __ __ _ | | | | | | | | _____ | | _ / _ \ | | / _` | | '_ \ / _` | | | | |_| | | |___ |_____| | |_| | | (_) | | | | (_| | | | | | | (_| | |___| \___/ \____| \____| \___/ |_| \__,_| |_| |_| \__, | |___/ Welcome to use ioc-golang! [Boot] Start to load ioc-golang config [Config] Load config file from ../conf/ioc_golang.yaml [Boot] Start to load debug [Debug] Debug mod is not enabled [Boot] Start to load autowire [Autowire Type] Found registered autowire type grpc [Autowire Struct Descriptor] Found type grpc registered SD github.com/alibaba/ioc-golang/example/autowire_grpc_client/api.HelloServiceClient [Autowire Type] Found registered autowire type singleton [Autowire Struct Descriptor] Found type singleton registered SD github.com/alibaba/ioc-golang/example/autowire_grpc_client/cmd/struct1.Struct1 [Autowire Struct Descriptor] Found type singleton registered SD main.App [Autowire Struct Descriptor] Found type singleton registered SD github.com/alibaba/ioc-golang/example/autowire_grpc_client/cmd/service1.Impl1 [Autowire Struct Descriptor] Found type singleton registered SD github.com/alibaba/ioc-golang/example/autowire_grpc_client/cmd/service2.Impl1 [Autowire Struct Descriptor] Found type singleton registered SD github.com/alibaba/ioc-golang/example/autowire_grpc_client/cmd/service2.Impl2 create conn target localhost:8080 App call grpc get: Hello laurence ExampleService1Impl1 call grpc get :Hello laurence ExampleService2Impl1 call grpc get :Hello laurence_service2_impl1 ExampleService2Impl2 call grpc get :Hello laurence_service2_impl2 ExampleStruct1 call grpc get :Hello laurence_service1_impl1
小节
gRPC 客户端注入能力,所代表的是 ioc-golang 框架具备网络模型注入的能力。
针对特定网络框架,可以在其服务提供者接口处,提供客户端注入代码,从而便于客户端引入后直接注入。