1. 程式人生 > >go微服務框架kratos學習筆記八 (kratos的依賴注入)

go微服務框架kratos學習筆記八 (kratos的依賴注入)

目錄

  • go微服務框架kratos學習筆記八(kratos的依賴注入)
    • 什麼是依賴注入
    • google wire
    • kratos中的wire
      • wire.NewSet
      • Binding Interfaces

go微服務框架kratos學習筆記八(kratos的依賴注入)


筆記二提過依賴注入,和如何生成,但沒有細講,本文來簡單看看kratos的依賴注入。

什麼是依賴注入

先來看一個小程式,

建立一個小程式模擬迎賓員問候客人的事件

我們將建立三個結構型別:

1)為迎賓員建立訊息 message
2)表達訊息的迎賓員 greeter
3)迎賓員問候客人的事件 event

type Message string

type Greeter struct {
    // ... TBD
}

type Event struct {
    // ... TBD
}

Message 僅僅攜帶一條string,現在我們建立一個簡單初始器

func NewMessage() Message {
    return Message("Hi there!")
}

我們的Greeter將需要引用這條訊息,讓我們建立一條初始器給Greeter

func NewGreeter(m Message) Greeter {
    return Greeter{Message: m}
}

type Greeter struct {
    Message Message // <- adding a Message field
}

在這個初始器中我們分配了Message 欄位給Greeter,現在我們能用Greeter的方法Greet來得到一條Message

func (g Greeter) Greet() Message {
    return g.Message
}

下一步,我們同樣也需要一個初始器用Event來建立一個Greeter

func NewEvent(g Greeter) Event {
    return Event{Greeter: g}
}

type Event struct {
    Greeter Greeter // <- adding a Greeter field
}

新增一個Start()來啟動事件

func (e Event) Start() {
    msg := e.Greeter.Greet()
    fmt.Println(msg)
}

Start即是我們小程式的核心,它告訴greeter去放出一條問候並打印出來。

現在我們小程式所有的元件就緒了,看看它是如何初始化所有元件的,它看起來可能是這樣的

func main() {
    message := NewMessage()
    greeter := NewGreeter(message)
    event := NewEvent(greeter)

    event.Start()
}

首先我們建立一條message,然後我們用message建立一個greeter,最後我們用greeter建立一個event.

這其實就是依賴注入dependency injection簡稱di的原理,

依賴注入基本上就是提供物件需要的物件(其依賴),而不是讓物件自己構造它們。

依賴注入能讓測試變的更為簡單,我們可以通過建構函式來進行注入。

SomeClass() has its constructor as following:

public SomeClass() {
    myObject = Factory.getObject();
}

例如,如果myObject包含複雜的任務像磁碟訪問或者網路訪問,那麼SomeClass將很難進行單元測試。程式必須模仿myObject並且需要模仿Factory呼叫

而將myObject作為引數傳遞給建構函式.

public SomeClass (MyClass myObject) {
    this.myObject = myObject;
}

myObject就能直接執行,使測試變的更為簡單。

可以通過多種方式將依賴項注入到物件中(例如建構函式注入或setter注入)。甚至可以使用專門的依賴項注入框架(例如Spring)來做到這一點,但是肯定不是必需的。不需要那些框架的依賴注入。顯式例項化和傳遞物件(依賴項)與框架注入一樣好。

google wire

kratos 使用的 google wire 就是golang的一個依賴注入解決的工具,這個工具能夠自動生成類的依賴關係。

依賴注入的一個缺點就是需要如此多的初始化步驟,讓我們看看如何使用Wire來讓初始化我們的元件變的更快.

將我們的小程式main函式改成如下形式:

func main() {
    e := InitializeEvent()

    e.Start()
}

下一步,分離一個檔案wire.go,我們定義InitializeEvent

// wire.go

func InitializeEvent() Event {
    wire.Build(NewEvent, NewGreeter, NewMessage)
    return Event{}
}

不是依次初始化每個元件並將其傳遞給下一個元件,而是通過一個wire.Build呼叫來構建我們想要的用的初始器。在Wire中,初始化器被稱為providers,一個提供特定型別的函式。

我們為Event新增一個零值作為返回值,以滿足編譯器的要求。
注意,即使我們向Event新增值,Wire也會忽略它們。
實際上,注入器的目的是提供關於使用哪些providers來構造Event的資訊。

InitializeEvent即是一個“注入器”。現在我們已經完成了注入器

然後在wire.go目錄下執行wire工具。

安裝

go get github.com/google/wire/cmd/wire

Wire將找到InitializeEvent注入器並生成一個函式,其主體由所有必要的初始化步驟填充。結果將被寫入名為wire_gen.go的檔案。

// wire_gen.go

func InitializeEvent() Event {
    message := NewMessage()
    greeter := NewGreeter(message)
    event := NewEvent(greeter)
    return event
}

這看上去就像我們上面手工寫的程式碼,想象一下,對於複雜得多的元件,Wire是多麼有用。

kratos中的wire

最後回來看看kratos中的wire.go

// +build wireinject
// The build tag makes sure the stub is not built in the final build.

package di

import (
    pb "demo/api"
    "demo/internal/dao"
    "demo/internal/server/grpc"
    "demo/internal/server/http"
    "demo/internal/service"

    "github.com/google/wire"
)

var daoProvider = wire.NewSet(dao.New, dao.NewDB, dao.NewRedis, dao.NewMC)
var serviceProvider = wire.NewSet(service.New, wire.Bind(new(pb.DemoServer), new(*service.Service)))

func InitApp() (*App, func(), error) {
    panic(wire.Build(daoProvider, serviceProvider, http.New, grpc.New, NewApp))
}

可以看到kratos用到了wire的一些其它介面:wire.NewSet,wire.Bind,簡單看看。

wire.NewSet

Wire有兩個核心概念:Providersinjectors

Providers

Wire中的主要機制是Providers:一個可以生成值的函式。這些函式都是普通的Go程式碼。

Providers 可以分組為provider sets,通過wire.NewSet函式可以新增一組providers到一個新的集合中。

var daoProvider = wire.NewSet(dao.New, dao.NewDB, dao.NewRedis, dao.NewMC)

當然也可以新增一個provider sets進一個provider sets

var MegaSet = wire.NewSet(daoProvider, pkg.OtherSet)

injector(注入器)

一個應用程式用injector連線這些providers: 一個按依賴順序呼叫providers的函式,即使用Wire,編寫注入器的簽名,然後Wire生成函式的主體。

呼叫wire.Build的函式則是來宣告注入器的,返回值不重要,只要型別正確即可。

func InitApp() (*App, func(), error) {
    panic(wire.Build(daoProvider, serviceProvider, http.New, grpc.New, NewApp))
}

Binding Interfaces

最後看看 wire.Bind 用來繫結介面的具體型別。

var serviceProvider = wire.NewSet(service.New, wire.Bind(new(pb.DemoServer), new(*service.Service)))

wire.Bind第一個引數 為指向所需介面型別的指標,第二個引數為 指向實現該介面型別的指標,

可以看到如果不加wire.Bind(new(pb.DemoServer), new(*service.Service)), 可以看到會找不到依賴。

相關推薦

go服務框架kratos學習筆記 (kratos依賴注入)

目錄 go微服務框架kratos學習筆記八(kratos的依賴注入) 什麼是依賴注入 google wire kratos中的wire wire.NewSet Binding

服務框架實踐——學習筆記

微服務實戰(一):微服務架構的優勢與不足 每個服務單獨使用一個database,這為資料庫CAP帶來挑戰. 例如,一個使用者完成一筆消費,同時影響購物車/推薦系統/評論系統等的資料.在單體式應用容易實現一致性,分散式微服務必須使用RPC或訊息佇列等通訊機制,開

# go服務框架kratos學習筆記六(kratos 服務發現 discovery)

目錄 go微服務框架kratos學習筆記六(kratos 服務發現 discovery) http api register 服務註冊 fetch 獲取例項 fetchs 批量獲取例項

go服務框架kratos學習筆記七(kratos warden 負載均衡 balancer)

目錄 go微服務框架kratos學習筆記七(kratos warden 負載均衡 balancer) demo demo server demo client 池 dao

go服務框架go-micro深度學習(一) 整體架構介紹

目前 連接 and 創建 tran 自己的 穩定 idt sort 產品嘴裏的一個小項目,從立項到開發上線,隨著時間和需求的不斷激增,會越來越復雜,變成一個大項目,如果前期項目架構沒設計的不好,代碼會越來越臃腫,難以維護,後期的每次產品叠代上線都會牽一發而動

go服務框架go-micro深度學習(三) Registry服務的註冊和發現

     服務的註冊與發現是微服務必不可少的功能,這樣系統才能有更高的效能,更高的可用性。go-micro框架的服務發現有自己能用的介面Registry。只要實現這個介面就可以定製自己的服務註冊和發現。     go-micro在客戶端做的負載,典型的Balancing-aware Client模式。  

go服務框架go-micro深度學習 rpc方法調用過程詳解

route head text Golan port 調用服務方法 eof 服務器 面試題 摘要: 上一篇帖子go微服務框架go-micro深度學習(三) Registry服務的註冊和發現詳細解釋了go-micro是如何做服務註冊和發現在,服務端註冊server信息,cli

阿里巴巴分散式服務框架dubbo學習筆記

Dubbo是什麼? Dubbo是一個分散式服務框架,致力於提供高效能和透明化的RPC遠端服務呼叫方案,以及SOA服務治理方案。簡單的說,dubbo就是個服務框架,如果沒有分散式的需求,其實是不需要用的,只有在分散式的時候,才有dubbo這樣的分散式服務框架的需求,並且本質上是個服務呼叫的東東,說

《深入理解Spring Cloud與服務構建》學習筆記(二)~使用Spring Boot配置檔案

接上一章demo: 一、IDEA在建立完Spring Boot專案時,會在src/main/resources目錄下生成一個application.properties檔案,使用者進行系統屬性配置,預設為空。Spring Boot也支援yml格式的檔案配置,當前使用yml檔案

《深入理解Spring Cloud與服務構建》學習筆記(五)~SpringBoot 整合 JPA

JPA是一個數據持久化的類和方法的集合,目前java專案開發中提到的JPA一般是指用Hibernate的實現,因為在java的ORM框架中,只有Hibernate實現的最好。當前學習在SpringBoot專案中使用JPA,資料庫使用mysql。 一、新建一個SpringBo

《深入理解Spring Cloud與服務構建》學習筆記(五)~SpringBoot 整合 Redis

Redis是一個開源的、先進的 key-value 儲存系統,可用於構建高效能的儲存系統。 Redis 支援資料結構有字串、雜湊、列表、集合、排序集合、點陣圖、超文字等。 NoSQL (Not Only SQL 泛指非關係型的資料庫。 Redis 是一種NoSQL, Redi

《深入理解Spring Cloud與服務構建》學習筆記(七)~SpringBoot 整合 Swagger2,搭建線上api文件

一、在專案 pom.xml 引入 swagger 依賴 springfox-swagger2 和 springfox-swagger-ui 如: <dependency> <groupId>io.springfox</groupId>

服務】Springcloud學習筆記(一) —— Eureka

SpringCloud基本特性 分散式配置中心 服務註冊/發現(Eureka) 智慧路由(Zuul) 服務間的呼叫 客戶端負載均衡(Ribbon) 斷路器(Hystrix) 分散式訊息管理

服務框架surging學習之路——序列化

成員 cor 傳輸 pack bubuko href 框架 跨語言 html 原文:微服務框架surging學習之路——序列化1.對微服務的理解   之前看到在群裏的朋友門都在討論微服務,看到他們的討論,我也有了一些自己的理解,所謂微服務就是系統裏的每個服務都 可以自由組

Spring4學習筆記----Spring的依賴注入詳解

Spring是一個IOC和AOP容器,Spring是非侵入型的,基於Spring開發的web應用中的物件可以不依賴Spring的API. IOC:依賴注入 (讓Spring Bean以配置檔案的形式組織在一起) 所謂依賴注入:在程式執行過程中,如需要另外一個物件協作(呼叫

golang服務框架go-micro 入門筆記2.1 micro工具之micro api

micro api micro 功能非常強大,本文將詳細闡述micro api 命令列的功能 重要的事情說3次 本文全部程式碼h

golang服務框架go-micro 入門筆記2.2 micro工具之應用利器micro web

micro web micro 功能非常強大,本文將詳細闡述micro web 命令列的功能 閱讀本文前你可能需要進行如下知識儲備

服務框架學習收錄鏈接(包括服務搭建中用到mybatis-plus等)

oot pos rbo HR http 框架 ref quick 收錄 1、基於Spring Boot和Spring Cloud實現微服務架構學習(一)-Spring框架介紹 https://blog.csdn.net/zeb_perfect/article/details

基於Kubernetes的機器學習服務系統設計系列——(三)RESTful服務框架

 內容提要 微服務框架 框架實現   基於Kubernetes的機器學習微服務系統設計——(1)概念與構想   為了微服務的介面互動統一,本系統採用統一的框架模式。採用Jersey軟體框架,Jersey 是開源的RESTful框架, 實現了J

信小程式學習筆記(一)之框架及工具

文章目錄 一、app.json的配置 1. 決定頁面檔案路徑 2. 配置視窗表現 3. 配置tab標籤導航 4. 設定網路超時時間 5. 配置debug模式 二、App()函式使用