应用开发思路
// +ioc:autowire=true
// +ioc:autowire:type=normal
// +ioc:autowire:paramType=Config
// +ioc:autowire:constructFunc=New
type RedisClient struct {
client *redis.Client
ServiceImpl1 Service `singleton:"main.ServiceImpl1"` // inject Service 's ServiceImpl1
}
type Config struct {
Address string
Password string
DB string
}
func (c *Config) New(impl *Impl) (*Impl, error) {
dbInt, err := strconv.Atoi(c.DB)
if err != nil {
return impl, err
}
client := redis.NewClient(&redis.Options{
Addr: c.Address,
Password: c.Password,
DB: dbInt,
})
_, err = client.Ping().Result()
if err != nil {
return impl, err
}
impl.client = client
return impl, nil
}
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
ServiceImpl1 Service `singleton:"main.ServiceImpl1"` // inject Service 's ServiceImpl1 implementation
RedisClientPtr *RedisClient `normal:",address=localhost:6379&db=0"` // inject RedisClient struct pointer
}
基于IOC-golang框架开发的,一个使用单例模式的对象 APP ,其依赖一个 Service 接口,该接口期望被 main.ServiceImpl1 单例模式结构注入;APP 还依赖一个 *RedisClient 结构体指针,期望以多例模式注入,并传入了参数。参数也可以从配置文件的结构默认位置读取。
如果按照常规的开发方式,开发者需要额外手动读取参数并创建依赖的 RedisClient 对象,手动组装 APP对象,维护单例模型指针,提供单例模型的构造函数等,这些逻辑都被 IOC-golang 封装好了。
对象生命周期
可扩展性
小结
项目层级
主要功能
强大、易用、可扩展的依赖注入能力,是框架的核心功能。
开发者可以将任何结构体注入至标签字段:
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
ServiceStruct *ServiceStruct `singleton:""` // inject ServiceStruct struct pointer
}
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
ServiceImpl1 ServiceInterface `singleton:"main.ServiceImpl1"` // inject ServiceInterface 's ServiceImpl1 implementation
}
可以通过 API 的方式,获取任何已注册的结构体:
// 该函数由 iocli 工具自动生成
func GetApp() (*App, error) {
i, err := singleton.GetImpl(util.GetSDIDByStructPtr(new(App)), nil)
if err != nil {
return nil, err
}
impl := i.(*App)
return impl, nil
}
// +ioc:autowire=true
// +ioc:autowire:type=singleton
type App struct {
NormalDB3Redis normalRedis.ImplIOCInterface `normal:",address=127.0.0.1:6379&db=3"`
}
通过 API 进行参数传递:
func main() {
client := redis.NewClient(&redis.Options{
Addr: p.RedisAddr,
})
}
autowire:
normal:
:
:
param:
nacosclientparam:
clientconfig:
appKey: appKey
serverconfigs:
ipaddr: 127.0.0.1
port: 8848
结构代理层:AOP
// +ioc:autowire=true// +ioc:autowire:type=singleton
type Impl1 struct {
}
func (i *Impl1) Hello(req string) string {
return req
}
开发者可以通过执行iocli gen命令,一键为工程内所有标注的结构生成代码,生成位于结构相同目录的zz_generated.ioc.go,其内容包括:
结构注册代码,会以结构描述符的形式,将结构生命周期注册到框架上。
func init() {
singleton.RegisterStructDescriptor(&autowire.StructDescriptor{
Factory: func() interface{} {
return &Impl1{}
},
})
}
结构专属接口,命名为 $(结构名)IOCInterface
type Impl1IOCInterface interface {
Hello(req string) string
}
结构代理层存根
框架会为所有结构提供代理层,在面向接口编程的场景下,所有请求都会经过代理层,扩展出强大的运维能力。
type impl1_ struct {
Hello_ func(req string) string
}
func (i *impl1_) Hello(req string) string {
return i.Hello_(req)
}
结构获取API
// 获取结构指针
func GetImpl1() (*Impl1, error) {
i, err := singleton.GetImpl(util.GetSDIDByStructPtr(new(Impl1)), nil)
if err != nil {
return nil, err
}
impl := i.(*Impl1)
return impl, nil
}
// 获取包装了代理层的专属接口
func GetImpl1IOCInterface() (Impl1IOCInterface, error) {
i, err := singleton.GetImplWithProxy(util.GetSDIDByStructPtr(new(Impl1)), nil)
if err != nil {
return nil, err
}
impl := i.(Impl1IOCInterface)
return impl, nil
}
以上代码均由工具自动生成,开发者只需使用即可。通过这些代码展示,我想传达给读者一个信息,就是 IOC-golang 可以管理任何对象的代理存根,这也就意味着,我们可以用这一层代理做任何想做的事情。其中就包括框架已经实现的能力:
结构展示:可以展示所有加载到框架的结构、方法列表
接口参数动态监听:可以监听运行态的 go 进程,展示当前正在执行的函数、参数值、返回值。
链路追踪:可以获取一个请求的完整调用链路,获取分布式场景下的跨进程调用链路,从而分析性能瓶颈。
但这些只是"运维"这个庞大的话题的冰山一角,我们基于结构代理 AOP 层 ,可以做任何我们能想到的事情:
HttpServer
IOC-golang 是一个崭新的项目,从第一行代码的编写,到今天不过一个月的时间。
我们的愿景是让 IOC-golang 成为 Go 应用开发的首选框架,让 Go 开发人员更贴近业务逻辑,减少冗余代码,增加代码的易读性,让 Go 生态的 “面向对象编程” 进入自动挡时代。
项目初创,十分期待能与感兴趣的开发者共创一片天地。
项目github地址: github.com/alibaba/ioc-golang
项目文档:ioc-golang.github.io
项目示例:ioc-golang/example
欢迎加入钉钉群“IOC-golang 交流群”:44638289
云原生环境下基于 Serverless 架构的创新应用
点击阅读原文查看详情。