yoyogo v1.7.5 釋出, 獨立依賴注入DI

YOYOFx發表於2021-07-15

YoyoGo v1.7.5 ?? YoyoGo (Go語言框架)

一個簡單、輕量、快速、基於依賴注入的微服務框架( web 、grpc ),支援Nacos/Consoul/Etcd/Eureka/k8s /Apollo等 .

https://github.com/yoyofx/yoyogo

v1.7.5 更新內容

Framework dependency:

Features:

  • Support grpc connection timeout with context. (fix)

Dependency injection

依賴注入是更廣泛的控制反轉技術的一種形式。它的作用是提高程式的模組化和可擴充套件性。

此次升級將DI獨立,以便之後整合更多外圍生態,開源地址: https://github.com/yoyofxteam/dependencyinjection

YoyoGO框架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}
}
// 高層API , 用於IOC宣告,不做DI容器表達。 支援三種生命週期如下:
// Singleton ServiceLifetime = 0 
// Scoped    ServiceLifetime = 1 
// Transient ServiceLifetime = 2
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

Installing

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
}

相關文章