最近在开发基于golang下的cqrs框架 https://github.com/berkaroad/squat (陆续开发中,最近断了半年,懒了。。。)。这个框架依赖ioc框架,因为之前写了一个ioc,所以借此完善下,主要从灵活性、易用性、性能角度进行了优化。顺带也支持了go mod,并将源码文件合并为单文件,方便有直接移植源码的人(license信息请保留,尊重著作权)。

  先来个直观的调用端对比(v1.2.0为新版,v0.1.1为旧版):

var container = ioc.NewContainer() // v0.1.1
var container = ioc.New() // v1.2.0,非必需,可以直接使用ioc.XXX 即使用内置全局Container // register service to *struct
container.Register(&Class2{Name: "Jerry Bai"}, ioc.Singleton) // v0.1.1
ioc.AddSingleton[*Class2](&Class2{Name: "Jerry Bai"}) // v1.2.0
container.Register(&Class1{}, ioc.Transient) // v0.1.1,调用函数InitFunc()获取初始化函数来完成初始化
ioc.AddTransient[*Class1](func() *Class1 { // v1.2.0,直接通过传入的函数来完成
var svc Class1
// inject to *struct
ioc.Inject(&svc) // v1.2.0,支持注入到结构体
} // register service to interface.
container.RegisterTo(&Class2{Name: "Jerry Bai"}, (*Interface2)(nil), ioc.Singleton) // v0.1.1
ioc.AddSingleton[Interface2](&Class2{Name: "Jerry Bai"}) // v1.2.0
container.RegisterTo(&Class1{}, (*Interface1)(nil), ioc.Transient) // v0.1.1,调用函数InitFunc()获取初始化函数来完成初始化
ioc.AddTransient[Interface1](func() Interface1 { // v1.2.0,直接通过传入的函数来完成
var svc Class1
// inject to *struct
ioc.Inject(&svc) // v1.2.0,支持注入到结构体
} // inject to function
ioc.Inject(func(c1 *Class1, c2 *Class2, i1 Interface1, i2 Interface2, resolver ioc.Resolver) { // v1.2.0
println("c1.C2Name=", c1.C2.Name)
println("c2.Name=", c2.Name)
println("i1.GetC2Name=()", i1.GetC2Name())
println("i2.GetName=()", i2.GetName())
})
container.Invoke(func(c1 *Class1, c2 *Class2, i1 Interface1, i2 Interface2, roContainer ioc.ReadonlyContainer) { // v0.1.1
println("c1.C2Name=", c1.C2Name)
println("c2.Name=", c2.Name)
println("i1.GetC2Name=()", i1.GetC2Name())
println("i2.GetName=()", i2.GetName())
})

  新版本,从功能角度,增加支持了结构体注入、泛型方式获取服务实例、替换已存在的服务。

// get service from ioc(go1.18开始支持泛型)
c1 := ioc.GetService[*Class1]
c2 := ioc.GetService[*Class2]
i1 := ioc.GetService[Interface1]
i2 := ioc.GetService[Interface2]
// override exists service(一般用于覆盖默认注入的对象)
c := ioc.New()
ioc.SetParent(c)
ioc.AddSingletonToC[Interface3](c, &Class3{Name: "Jerry Bai"}) // add service to parent's container
i3 := ioc.GetService[Interface3]() // *Class3, 'Interface3' only exists in parent's container
ioc.AddSingleton[Interface3](&Class4{Name: "Jerry Bai"}) // add service to global's container
i3 = ioc.GetService[Interface3]() // *Class4, 'Interface3' exists in both global and parent's container

  对结构体初始化的函数定义(模拟构造函数),从固定获取函数的接口 interface{InitFunc() interface{}} 改为按函数名获取(默认为 Initialize)。

type Class2 struct {
Name string
resolver ioc.Resolver
} func (c *Class2) Initialize(resolver ioc.Resolver) string {
c.resolver = resolver
return c.Name
} type Class3 struct {
Name string
resolver ioc.Resolver
} // specific custom initialize method name
func (c *Class3) InitializeMethodName() string {
return "MyInitialize"
} // custom initialize method
func (c *Class3) MyInitialize(resolver ioc.Resolver) string {
c.resolver = resolver
return c.Name
}

以下是新版本的性能测试。带 “Native” 的为原生调用,具体测试代码,参见源码:https://github.com/berkaroad/ioc/blob/master/benchmark_test.go

go test -run=none -count=1 -benchtime=1000000x -benchmem -bench=. ./...

goos: linux
goarch: amd64
pkg: github.com/berkaroad/ioc
cpu: AMD Ryzen 7 5800H with Radeon Graphics
BenchmarkGetSingletonService-4 1000000 26.16 ns/op 0 B/op 0 allocs/op
BenchmarkGetTransientService-4 1000000 370.9 ns/op 48 B/op 1 allocs/op
BenchmarkGetTransientServiceNative-4 1000000 131.9 ns/op 48 B/op 1 allocs/op
BenchmarkInjectToFunc-4 1000000 659.5 ns/op 144 B/op 5 allocs/op
BenchmarkInjectToFuncNative-4 1000000 89.26 ns/op 0 B/op 0 allocs/op
BenchmarkInjectToStruct-4 1000000 311.7 ns/op 0 B/op 0 allocs/op
BenchmarkInjectToStructNative-4 1000000 87.64 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/berkaroad/ioc 1.686s

---------------------------------分割线-------------------------------------------------------------

我的ioc项目,已经挂在github上,有兴趣的可以去了解下。https://github.com/berkaroad/ioc

使用中有何问题,欢迎在github上给我提issue,谢谢!

golang 依赖控制反转(IoC) 改进版的更多相关文章

  1. golang 依赖控制反转(IoC)

    主流开发语言,为了达到项目间的低耦合,都会借助IoC框架来实现.即抽象和实现分离,使用抽象层,不用关心这些抽象层的具体实现:抽象层的实现,可以独立实现.现在比较流行的领域驱动设计(ddd),为了达到将 ...

  2. 浅析“依赖注入(DI)/控制反转(IOC)”的实现思路

    开始学习Spring的时候,对依赖注入(DI)——也叫控制反转(IOC)—— 的理解不是很深刻.随着学习的深入,也逐渐有了自己的认识,在此记录,也希望能帮助其他入门同学更深入地理解Spring.本文不 ...

  3. 控制反转IOC的依赖注入方式

    引言: 项目中遇到关于IOC的一些内容,因为和正常的逻辑代码比较起来,IOC有点反常.因此本文记录IOC的一些基础知识,并附有相应的简单实例,而在实际项目中再复杂的应用也只是在基本应用的基础上扩展而来 ...

  4. 控制反转IOC与依赖注入DI

    理解 IOC  http://www.cnblogs.com/zhangchenliang/archive/2013/01/08/2850970.html IOC 相关实例      的http:// ...

  5. 控制反转(Ioc)和依赖注入(DI)

    控制反转IOC, 全称 “Inversion of Control”.依赖注入DI, 全称 “Dependency Injection”. 面向的问题:软件开发中,为了降低模块间.类间的耦合度,提倡基 ...

  6. 控制反转IOC与依赖注入DI【转】

    转自:http://my.oschina.net/1pei/blog/492601 一直对控制反转.依赖注入不太明白,看到这篇文章感觉有点懂了,介绍的很详细. 1. IoC理论的背景我们都知道,在采用 ...

  7. 依赖注入(DI)和控制反转(IOC)

    依赖注入(DI)和控制反转(IOC) 0X1 什么是依赖注入 依赖注入(Dependency Injection),是这样一个过程:某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只 ...

  8. iOS控制反转(IoC)与依赖注入(DI)的实现

    背景 最近接触了一段时间的SpringMVC,对其控制反转(IoC)和依赖注入(DI)印象深刻,此后便一直在思考如何使用OC语言较好的实现这两个功能.Java语言自带的注解特性为IoC和DI带来了极大 ...

  9. 个人对【依赖倒置(DIP)】、【控制反转(IOC)】、【依赖注入(DI)】浅显理解

    一.依赖倒置(Dependency Inversion Principle) 依赖倒置是面向对象设计领域的一种软件设计原则.(其他的设计原则还有:单一职责原则.开放封闭原则.里式替换原则.接口分离原则 ...

  10. 【转载】浅析依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI)

    原文地址 http://blog.csdn.net/briblue/article/details/75093382 写这篇文章的原因是这两天在编写关于 Dagger2 主题的博文时,花了大量的精力来 ...

随机推荐

  1. Zookeeper-ZKFC的原理和功能

    一.前言 HADOOP2 HA架构引入了ZKFC.Journalnode组件,本篇文章主要介绍ZKFC的功能和原理.HA架构支持两种切换方式: 手动切换:  通过命令实现主备之间的切换,可以用HDFS ...

  2. Java设计模式-原型模式Prototype

    介绍 当我们有一个类的实例(Prototype)并且我们想通过复制原型来创建新对象时,通常使用Prototype模式. 原型模式是一种创建型设计模式.能够复制已有对象, 而又无需使代码依赖它们所属的类 ...

  3. 使用ORACLE外部表装载复杂数据

    原文:http://www.oracle.com/technetwork/issue-archive/2013/13-jan/o13asktom-1886639.html I am using SQL ...

  4. python利用random模块随机生成MAC地址和IP地址

      import random   def randomMac(): macstring = "0123456789abcdef"*12 macstringlist=random. ...

  5. zookeeper源码(09)follower处理客户端请求

    在zookeeper中,follower也可以接收客户端连接,处理客户端请求,本文将分析follower处理客户端请求的流程: 读请求处理 写请求转发与响应 follower接收转发客户端请求 网络层 ...

  6. java数组实现的超市管理系统(控制台)

    说明:使用数组存储数据,针对用户功能1:增加用户2:删除用户3:修改用户:针对商品功能:1.显示所有商品2.修改商品信息3.添加商品信息4.删除商品信息5.查询商品信息 效果展示 ========== ...

  7. ECharts渐变温度直方图

    ECharts渐变直方图,根据具体的值调整色带,使所有颜色看起来协调一致. 直接在series数组中的对象中添加如下代码即可: itemStyle: { color: function (params ...

  8. 【Azure Redis 缓存】Azure Cache for Redis 如何迁移

    Azure Cache for Redis 如何迁移 [Azure Redis 缓存]Azure Cache for Redis有默认备份可以用于恢复么?一文中,介绍了使用RDB文件的方式来迁移Red ...

  9. Frechet Inception Distance

    (以下内容重新更新,主要讲解FID的意义,为何FID能够表示生成图像的多样性和质量,为什么FID越小,则图像多样性越好,质量也越好) 在计算FID中我们也同样使用inception network网络 ...

  10. Java 常用类 于 StringBuffer 和 StringBuilder的使用 + String三者的异同

    1 package com.bytezero.stringclass; 2 3 import org.junit.Test; 4 5 /** 6 * 关于 StringBuffer 和 StringB ...