当前位置: 首页 > news >正文

长安链源码学习v2.2.1--ioc机制(九)

长安链技术不断迭代,距离前面的教程已经过去一年多,迭代非常多的功能与特性,本次基于2.2.1版本继续学习长安链源码,相比早期教程,给阅读带来一定复杂度的是IOC,我们先来分析它。

1. 介绍

关于ioc的含义,网上的介绍有很多,这里不多赘述。简单来说这是一种降低模块间耦合的方式,在运行期间动态关联对象的某种实现。

ioc机制在长安链store 存储模块中使用较多,例如:根据配置加载区块存储引擎,文件形式、KV形式、SQL形式等。IOC代码位置在chainmaker.org/chainmaker/common/v2/container

2. 使用方法

2.1 简单使用1

通过一个例子来学习,首先找一个干净的工程:

1)定义区块存储接口

type BlockStore interface {
	Set(key, vaule string)
	Get(key string) string
}

2)文件存储实现上述接口,注意NewFileStore方法的返回值是interface

type FileStore struct {

}

//注意该方法的返回值是interface
func NewFileStore() BlockStore{
	return &FileStore{}
}

func (*FileStore) Set(key, vaule string) {

}

func (*FileStore) Get(key string) string {
	return "filestore-get"
}

3)通过IOC实现依赖注入,通过Register方法将生成文件存储对象的方法注册到IOC中心,通过Resolvebs接口说对象与FileStore实现对象关联。(如果chainmaker.org/chainmaker/common/v2/container找不到,可用过go mod tidy拉取。)

import (
    "fmt"

	"chainmaker.org/chainmaker/common/v2/container"
)

func main() {
	c := container.NewContainer()
	err := c.Register(NewFileStore)
	if err != nil {
		panic(err)
	}

	var bs BlockStore
	err = c.Resolve(&bs)
	if err != nil {
		panic(err)
	}
	fmt.Println(bs.Get("123"))
}
2.2 简单使用2

1)定义区块存储接口(这步骤不变)

type BlockStore interface {
	Set(key, vaule string)
	Get(key string) string
}

2)文件存储实现上述接口,注意NewFileStore方法的返回值是struct

type FileStore struct {

}

//注意该方法的返回值是数据结构
func NewFileStore() *FileStore{
	return &FileStore{}
}

func (*FileStore) Set(key, vaule string) {

}

func (*FileStore) Get(key string) string {
	return "filestore-get"
}

3)通过IOC实现依赖注入,这里使用container.Interface ,含义是不理会NewFileStore返回值类型,根据container.Interface中的类型绑定NewFileStore实现。

import (
	"chainmaker.org/chainmaker/common/v2/container"
	"fmt"
)

func main() {
	c := container.NewContainer()
	var bsi BlockStore
	err := c.Register(NewFileStore, container.Interface(&bsi))
	if err != nil {
		panic(err)
	}

	var bs BlockStore
	err = c.Resolve(&bs)
	if err != nil {
		panic(err)
	}
	fmt.Println(bs.Get("123"))
}
2.3 同一接口多种实现

增加一种BlockStore实现方式:KV数据库实现

type KVStore struct {

}

//注意该方法的返回值是数据结构
func NewKVStore() *KVStore {
	return &KVStore {}
}

func (*KVStore ) Set(key, vaule string) {

}

func (*KVStore ) Get(key string) string {
	return "kvstore-get"
}

默认绑定第一个实现对象(NewFileStore),配置container.Default()优先绑定,下面的案例绑定NewKVStore

import (
	"chainmaker.org/chainmaker/common/v2/container"
	"fmt"
)

func main() {
	c := container.NewContainer()
	var bsi BlockStore
	err := c.Register(NewFileStore, container.Interface(&bsi))
	if err != nil {
		panic(err)
	}

	err = c.Register(NewKVStore, container.Interface(&bsi), container.Default())
	if err != nil {
		panic(err)
	}

	var bs BlockStore
	err = c.Resolve(&bs)
	if err != nil {
		panic(err)
	}
	fmt.Println(bs.Get("123"))
}
2.3 构造方法带参数

把KVStore删除,本Case模拟不需要。构造方法增加一个flag并打印flag的值。

type FileStore struct {

}

func NewFileStore(flag string) *FileStore{
	fmt.Println(flag)
	return &FileStore{}
}

func (*FileStore) Set(key, vaule string) {

}

func (*FileStore) Get(key string) string {
	return "filestore-get"
}

在Register期间补充默认参数container.Parameters, 在Resolve绑定期间可以替换该参数container.Arguments,下面例子输出为Arguments

import (
	"fmt"
	
	"chainmaker.org/chainmaker/common/v2/container"
)

func main() {
	c := container.NewContainer()
	var bsi BlockStore
	err := c.Register(NewFileStore, container.Interface(&bsi), container.Parameters(map[int]interface{}{0: "Parameters"}))
	if err != nil {
		panic(err)
	}

	var bs BlockStore
	err = c.Resolve(&bs, container.Arguments(map[int]interface{}{0: "Arguments"}))
	if err != nil {
		panic(err)
	}
	fmt.Println(bs.Get("123"))
}
2.4 其他

上面几种用法是比较常见长安链中的使用方法,还有其他用法:
1)除了上述Default方式外,可在Resolve期间使用ResolveName指定绑定实现的名称,该名称在Register期间设置。
2)IOC单例与多例的设置Lifestyle
3)支持构造方法参数忽略Optional
4)构造方法的参数需要依赖其他IOC对象,依靠DependsOn绑定实现

思考:

在学习长安链IOC机制的时候,一直在思考使用IOC的必要性,关于这点并没有在官方资料上找到,相信官方团队有自己的考量,后续将持续关注官方文档资料,将设计思想补充到本节。

相关文章:

  • 面试必备:《Java 最常见 200+ 面试题全解析》
  • 抖音短视频运营规划内容孵化计划书模板
  • Leetcode 946.验证栈序列
  • CREO:利用CREO软件实现装配设计之四连杆机构设计案例应用(图文教程)之详细攻略
  • 基于数字孪生的智慧城市是如何发展的?
  • STL——list使用和模拟
  • 缓存怎么测试?
  • 智能控制理论及应用 王耀南等编著
  • 修改centos中Mysql( mariadb)数据默认存储位置
  • 神经网络编程教程入门课,人工神经网络编程内容
  • 零基础学Java有哪些必看书?推荐这5本
  • Python语句和循环
  • 阿里巴巴微服务核心手册:Spring Boot+Spring cloud+Dubbo
  • ssm基于微信小程序的社区老人健康管理服务系统的设计与实现毕业设计源码011513
  • opencv-python之位平面分解与数字水印
  • @jsonView过滤属性
  • 0基础学习移动端适配
  • 2017前端实习生面试总结
  • docker python 配置
  • IndexedDB
  • Javascript基础之Array数组API
  • nginx 负载服务器优化
  • PAT A1092
  • React+TypeScript入门
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 删除表内多余的重复数据
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 小程序01:wepy框架整合iview webapp UI
  • 译米田引理
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • #define与typedef区别
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • #微信小程序:微信小程序常见的配置传值
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (2015)JS ES6 必知的十个 特性
  • (9)STL算法之逆转旋转
  • (阿里云万网)-域名注册购买实名流程
  • (分享)自己整理的一些简单awk实用语句
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (一)kafka实战——kafka源码编译启动
  • (转) Android中ViewStub组件使用
  • (转)C#调用WebService 基础
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .java 9 找不到符号_java找不到符号
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .NET/C# 使用反射注册事件
  • .NET8.0 AOT 经验分享 FreeSql/FreeRedis/FreeScheduler 均已通过测试
  • .NET中使用Redis (二)
  • ??eclipse的安装配置问题!??