AOP 與擴充機制
1. 擴充模組與 init 方法
1.1 介面與實作
Golang 中的一個介面通常伴隨著多個實作類別,dubbo-go 為介面實作類別提供了一個可插拔且可擴充的機制。降低模組之間的耦合性,讓開發者更容易引入和客製化元件。
1.2 Golang 中的 init 方法
init 方法是 Golang 中的一個特殊方法。當使用者引入一組模組後,程式啟動時會先執行這些模組中的 init 方法來執行載入邏輯。這個方法是 dubbogo 註冊擴充元件的重要方式。
1.3 擴充模組
在框架原始碼中,有一個特殊的模組:common/extension,它負責快取所有可擴充元件的實作。
以負載平衡模組為例:common/extension/loadbalance.go
package extension
import (
"dubbo.apache.org/dubbo-go/v3/cluster/loadbalance"
)
var loadbalances = make(map[string]func() loadbalance. LoadBalance)
// SetLoadbalance sets the loadbalance extension with @name
// For example: random/round_robin/consistent_hash/least_active/...
func SetLoadbalance(name string, fcn func() loadbalance. LoadBalance) {
loadbalances[name] = fcn
}
// GetLoadbalance finds the loadbalance extension with @name
func GetLoadbalance(name string) loadbalance. LoadBalance {
if loadbalances[name] == nil {
panic("loadbalance for " + name + " is not existing, make sure you have import the package.")
}
return loadbalances[name]()
}
這個模組包含 Get 方法和 Set 方法。Get 方法會返回已實例化的 LoadBalance 介面,Set 方法則用於註冊工廠函式,並使用 map 來快取工廠函式。
當使用者導入 _ “dubbo.apache.org/dubbo-go/v3/cluster/loadbalance/random” 時,對應模組的 init 函式將被載入,並呼叫 Set 方法註冊唯一的鍵值和工廠函式,並將它們新增到上述的 map 中。
cluster/loadbalance/random/loadbalance.go
package random
import (
"math/rand"
)
import (
"dubbo.apache.org/dubbo-go/v3/cluster/loadbalance"
"dubbo.apache.org/dubbo-go/v3/common/constant"
"dubbo.apache.org/dubbo-go/v3/common/extension"
"dubbo.apache.org/dubbo-go/v3/protocol"
)
func init() {
extension.SetLoadbalance(constant.LoadBalanceKeyRandom, NewRandomLoadBalance)
}
到目前為止,當所有 init 方法都執行完畢後,就可以透過擴充模組的 Get 方法取得已實例化的物件。
1.4 導入模組
dubbogo 將所有內建模組放在 imports/imports.go 中。當使用者使用框架時,需要導入這個模組才能使用框架提供的基本功能。
import (
_ "dubbo.apache.org/dubbo-go/v3/imports"
)
2. 元件載入流程
使用者在程式碼中導入 _ “dubbo.apache.org/dubbo-go/v3/imports”
程式啟動時,會依序執行 init 函式,并将工厂函数/实例化对象注册到扩展模块中。
框架啟動時,會載入配置,從配置中取得要載入的模組的鍵值,并根據鍵值取得實例化對象。
使用者也可以手動調用擴展的 Get 方法,取得實例化對象并直接使用。
3. 自訂組件
在上述介紹的基礎上,開發者可以參考內建模組的範例,編寫自訂的擴展組件。
4. 面向切面程式設計 (AOP)
在 Dubbo-go 服務框架中,許多介面是基於 AOP 的思想設計的,例如 Invoker、Filter、LoadBalance、Router。
這些介面的多個實作通常會形成一組呼叫鏈,而單個實作類別只處理其關心的邏輯。
延伸閱讀:[AOP 維基百科]