yoyogo-diGo 语言依赖注入框架

联合创作 · 2023-09-30 06:52

Dependency injection 依赖注入是更广泛的控制反转技术的一种形式。它的作用是提高程序的模块化和可扩展性。

此次升级将 DI 独立,以便之后集成更多外围生态,开源地址:https://github.com/yoyofxteam/dependencyinjection

它分为(高/低)层API接口,下面展示下高层API:

type A struct {
	Name string
}

func NewA() *A {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	name := "A-" + strconv.Itoa(r.Int())
	return &A{Name: ls}
}

services := NewServiceCollection()
services.AddSingleton(NewA)
//serviceCollection.AddSingletonByImplementsAndName("redis-master", NewRedis, new(abstractions.IDataSource))
//serviceCollection.AddTransientByImplements(NewRedisClient, new(redis.IClient))
//serviceCollection.AddTransientByImplements(NewRedisHealthIndicator, new(health.Indicator))
serviceProvider := services.Build()

var env *A
_ = serviceProvider.GetService(&env) // used

框架安装

go get -u github.com/yoyofxteam/dependencyinjection@v1.0.0

服务提供者

首先服务提供者都是以构造器的形式提供的,我们需要创建两个基本类型:http.server和http.ServeMux。让我们创建一个简单的构造函数来初始化它

// NewServer creates a http server with provided mux as handler.
func NewServer(mux *http.ServeMux) *http.Server {    
    return &http.Server{
        Handler: mux,
    }
}

// NewServeMux creates a new http serve mux.
func NewServeMux() *http.ServeMux {    
    return &http.ServeMux{}
}

支持的构造器签名如下

func([dep1, dep2, depN]) (result, [cleanup, error])

构建一个DI容器

import (
  di "github.com/yoyofxteam/dependencyinjection"
)

container := di.New(    // provide http server
    di.Provide(NewServer),    // provide http serve mux
    di.Provide(NewServeMux)
)

获取容器中的实例

// declare type variable
var server *http.Server
// extracting
err := container.Extract(&server)
if err != nil {    
// check extraction error
}

server.ListenAndServe()

注册Naming定义提供者

// MasterDatabase provide write database access.
type MasterDatabase struct {
    *Database
}  // SlaveDatabase provide read database access.
type SlaveDatabase struct {
    *Database
} // provide master database

di.Provide(NewMasterDatabase, di.WithName("master"))
// provide slave database
di.Provide(NewSlaveDatabase, di.WithName("slave"))

var database *Database
err := container.Extract(&database,di.Name(master))  // get master databse

依赖关联

可能实际的情况,类型间会有大量依赖,组件A依赖组件B,这种情况我们使用 di.Parameter 来声明结构体,对其它提供者提供多依赖管理:

// ServiceParameters
type ServiceParameters struct {
    di.Parameter
    MasterDatabase *Database `di:"master"`
    SlaveDatabase *Database  `di:"slave,optional"`   // optional 可选参数,如果没有实例则为nil}// NewService creates new service with provided parameters.func NewService(parameters ServiceParameters) *Service {    return &Service{
        MasterDatabase:  parameters.MasterDatabase,
        SlaveDatabase: parameters.SlaveDatabase,
    }
}

Cleanup函数

提供者构造器返回清理函数用于销毁实例和释放资源,它由容器的container.Cleanup()函数统一管理:

func NewFile(log Logger, path Path) (*os.File, func(), error) {
    f, err := os.Open(string(path))    if err != nil {        return nil, nil, err
    }
    cleanup := func() {        if err := f.Close(); err != nil {
            log.Log(err)
        }
    }    return f, cleanup, nil
}

此项目已集成到 yoyogo框架中:

gitee:    https://gitee.com/yoyofx/yoyogo            github:  https://github.com/yoyofx/yoyogo

🦄🌈 YoyoGo 一个简单、轻量、快速、基于依赖注入的微服务框架( web 、grpc、xxl-job、console ),支持的注册中心 Nacos/Consoul/Etcd/Eureka/k8s 等。

浏览 4
点赞
评论
收藏
分享

手机扫一扫分享

编辑 分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

编辑 分享
举报