1 - redis 客户端注入

简介

本示例展示了注入 Redis 客户端能力。

在应用开发过程中,通过 SDK 操作 Redis 是一个常见的诉求。

ioc-golang 框架提供了注入 Redis 连接的能力,开发者可以在配置文件中指定好 Redis 地址、密码、db名等信息,通过标签注入连接,无需手动创建、组装。

注入模型与结构

多例(normal)依赖注入模型

预定义的 redis 结构

关键代码

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 的值。

2 - GORM 客户端注入

简介

本示例展示了注入基于 GORM 的数据库客户端能力。

在应用开发过程中,通过 SDK 操作数据库是一个常见的诉求,GORM 是应用较广泛的 Go 数据库 sdk。

ioc-golang 框架提供了注入数据库连接的能力,开发者可以在配置文件中指定好数据库地址、密码信息,通过标签注入连接,无需手动创建、组装 GORM 客户端。

注入模型与结构

多例(normal)依赖注入模型

预定义的 mysql 结构

关键代码

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
    }
    

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 中的数据。