一、前言

依赖注入相信大家都不陌生也不是什么新鲜的概念了,笔者初次深切体会依赖注入这种设计模式是在16年笔者在学习phalapi框架时使用的DI()函数,简单来说就是将所有的资源初始化集中在一起,通过统一的容器对外提供,而不是通过全局变量或到处New的方式。最近在学习kratos又看到一个团队的历史项目都使用wier,一个是正面教材一个是反面教材也有一些自己的思考,希望能够分享出来和大家交流交流。

资料如下:

  • wier官方文档:https://github.com/google/wire
  • kratos依赖注入:https://go-kratos.dev/docs/guide/wire
  • phalapi依赖注入:http://www.phalapi.net/wikis/2-11.html

二、依赖注入解决什么问题?

其实笔者开始写Goalng包括团队内部自己研发的小框架go-core主要使用的是资源容器的方式,框架帮助你将资源统一的容器管理起来(也是一种间接的全局变量的方式,只是不能直接进行修改),但对于业务分层如果是微服务的话足够简单就直接 packagename.funcname 进行调用,如果是稍微复杂一些的项目用一个空的status的全局变量来提供func的隔离。

但这样的设计会存在一下几个问题:

  • 依赖不清晰:

    • 虽然限定了调用层级,但无法直观了解当前模块依赖那些下层模块
  • 资源获取僵化不灵活:
    • 资源获取在最底层虽然可以也实现多态,但影响范围只能是全局,无法控制作用域
  • 避免犯错:
    • 无论是容器资源管理还是全局status变量都存在被误操作的可能性

三、一个糟糕的依赖注入的设计

如果你使用成熟框架无论是go-zero或kratos都应该按照他们的最佳实践来执行,如果是框架层没有约束还是要更具自己的实际情况来进行选择,有限选择最简单的方式顺应研发人员的直觉,设计模式如果用不对那将是场灾难,就和最近接触到了一个项目虽然使用了wier作为依赖注入,但是用的一塌糊涂:

它存在的问题:

  • 貌似依赖注入了又貌似没有

    • 一个大对象实例化了保管了所有资源
    • 获取资源还是在使用New的方式
    • 应为需要New所以下次实例化需要的资源也变成了当前这一层的依赖,需要一层一层将资源传递下去
    • 所有入口资源都依赖了一个全局的大资源

一个设计模式如果没有用对,虽然解决了上面资源共享的问题,但是又带来了一堆奇怪的问题,真的是得不偿失。所以架构也好业务也好都是逐步演进过来的,不要将设计模式当做万能药,第一性原则还是保持简单和高内聚低耦合,遇到文件引入对应的方案然后需要做好落地的最佳实践。

四、怎样是一个好的依赖注入?

当笔者接触到上面的项目之后就非常的迷茫,在思考怎么样才是一个好的依赖注入设计模式的落地呢?当接触到 kratos 之后给了我一些启发:

一个好的依赖注入需要具备哪些特性

  • 编码过程中所有的依赖都只能从自身对象实例中获取,不允许New或使用全局变量
  • 依赖注入过程要贯穿全流程,从grpc服务或http服务初始化开始而不是从业务才开始使用

bilibili/kratos × google/wire 标准样例:

// 定义依赖关系,从头到尾
func wireApp(*conf.Server, *conf.Data, log.Logger) (*kratos.App, func(), error) {panic(wire.Build(server.ProviderSet,data.ProviderSet,biz.ProviderSet,service.ProviderSet,newApp))
}// 初始化方法也要参与依赖注入
func newApp(logger log.Logger, gs *grpc.Server, hs *http.Server) *kratos.App {return kratos.New(kratos.ID(id),kratos.Name(Name),kratos.Version(Version),kratos.Metadata(map[string]string{}),kratos.Logger(logger),kratos.Server(gs,hs,),)
}// 程序启动直接从wier生成的方法中获取app, cleanup, err := wireApp(bc.Server, bc.Data, logger)if err != nil {panic(err)}defer cleanup()// start and wait for stop signalif err := app.Run(); err != nil {panic(err)}

依赖的资源都是局部的,并且只关注自己所依赖的范围,依赖的依赖怎么注入不应该被关注

// GreeterService is a greeter service.
type GreeterService struct {v1.UnimplementedGreeterServeruc *biz.GreeterUsecase
}// NewGreeterService new a greeter service.
func NewGreeterService(uc *biz.GreeterUsecase) *GreeterService {return &GreeterService{uc: uc}
}...
// GreeterUsecase is a Greeter usecase.
type GreeterUsecase struct {repo GreeterRepolog  *log.Helper
}// NewGreeterUsecase new a Greeter usecase.
func NewGreeterUsecase(repo GreeterRepo, logger log.Logger) *GreeterUsecase {return &GreeterUsecase{repo: repo, log: log.NewHelper(logger)}
}

依赖注入的正确打开方式 bilibili/kratos × google/wire相关推荐

  1. opengl 贴图坐标控制_材质贴图正确打开方式

    哈喽,各位观众朋友们好鸭~欢迎来到讲道理画图的地方,我是黄玮宁. 最近呀经常有小伙伴来问我那些不同通道的材质贴图该怎么用,而且频率不是一般的高,所以我觉得有必要来说说这些通道贴图的用法了. 视频版(B ...

  2. 通过机器学习识别“迪士尼在逃公主”,程序员宠女的正确打开方式!

    到了庆祝的时候了!我们刚刚送走了圣诞老人.现在正等待新年的钟声敲响.所以我想到建立一个很酷的东西(至少我的七岁小公主会觉得)同时学一点机器学习.所以我们要做一个什么? 我借用的我女儿所有迪士尼公主人偶 ...

  3. [分布式训练] 单机多卡的正确打开方式:理论基础

    [分布式训练] 单机多卡的正确打开方式:理论基础 转自:https://fyubang.com/2019/07/08/distributed-training/ 瓦砾由于最近bert-large用的比 ...

  4. 拜托!这才是分布式系统CAP的正确打开方式!

    "纸面"上的CAP 相信很多同学都听过CAP这个理论,为了避免我们认知不同,我们先来统一下知识起点. CAP理论在1999年一经提出就成为了分布式系统领域的顶级教义.并表明分布式服 ...

  5. lambda学习视频和stream学习视频(Java8 Lambda表达式视频教程)-Java爬虫-网络购物的正确打开方式

    百度网盘 链接:https://pan.baidu.com/s/1upU5EVXOQeho6poDYdnhiQ 提取码:088l Java8 Lambda表达式视频教程 https://www.bil ...

  6. Spring系列之依赖注入的三种方式

    目录 一.依赖注入方式 1.使用属性的setXXX方法注入 2.构造函数注入 (1)按类型匹配入参type (2)按索引匹配入参index (3)联合使用类型和索引匹配入参[type和index一起使 ...

  7. 肖秀荣、陆寓丰、徐涛三大名师的正确“打开方式”

    考研政治怎么学? 肖秀荣.陆寓丰.徐涛 三大名师的正确"打开方式" HEY 暑假黄金期到达尾声,是不是有很多小伙伴还没有开始政治复习?或者复习的迷迷糊糊? 今天笔者会为大家进行全面 ...

  8. 二次元的正确打开方式

    本文 GitHub https://github.com/Jack-Cherish/PythonPark 已收录,有技术干货文章,整理的学习资料,一线大厂面试经验分享等,欢迎 Star 和 完善. 一 ...

  9. android动态设置错误页面,Android缺省页的正确打开方式(优雅的处理loading、error、empty...

    Android缺省页的正确打开方式(优雅的处理loading.error.empty Android缺省页的正确打开方式(优雅的处理loading.error.empty各种状态缺省) MultiSt ...

最新文章

  1. mysql sleep详解_mysql sleep链接过多的原因及解决办法
  2. 5G信令(就是用户身份信息)——手机开机后,先从USIM中读取之前运营商分配的临时身份信息GUTI/TMSI,发送携带该身份信息的信令给基站,请求接入运营商网络。...
  3. python是动态类型语言、变量不需要显示声明类型_【IT专家】第3章 Python基础
  4. matlab中句柄图性对像的设置
  5. 【MM模块】Source Lists 货源清单
  6. HP LoadRunner 12.02 Tutorial T7177-88037教程独家中文版
  7. YbtOJ#883-最大的割【带修线性基】
  8. 前端学习(1687):前端系列javascript基础面试前言
  9. uniapp ajax数据库查询,uniapp小程序登录、数据请求方式
  10. 根据list中某个字段的值排序_MySql中常用函数
  11. 《机器学习实战》学习总结(五)K-means算法原理
  12. 会畅通讯登陆创业板上市,CEO黄元庚说云视频是下一个万亿级市场
  13. 基于SSH框架社区智能化管理系统答辩PPT模板
  14. 教你定时爬取微博热搜榜并做动态数据展示,让你不错过任何一个吃瓜热点
  15. python3.6+Appium实现手机微信自动回复
  16. python零基础教学plc_Python从基础到开发精修全面学习视频教程
  17. github+gitee上传源码 git工具的安装和使用
  18. ndows movie maker,Windows Movie Maker
  19. 用U盘安装Windows server 2012 R2
  20. javascript 图片特效算法

热门文章

  1. Deepin Linux15 华为荣耀笔记本MagicBook2019使用-安装深度应用商店和应用软件
  2. crontab 每5秒钟执行一次
  3. PHP 将xml文件解析为数组
  4. TDSQL-C PostgreSQL(CynosDB) 内核解密-披荆斩棘,勇往直前的腾讯云数据库
  5. 解决Maven:Cannot resolve com.oracle.ojdbc:ojdbc6:11.2.0.1.0报红找不到问题,解决方案亲测有效详细图文教程 问题描述
  6. 转行程序员日记--2020-08-10
  7. bread是可数还是不可数_bread可数吗
  8. 【华为云技术分享】华为云弹性云服务器ECS搭建FTP服务实践
  9. google map v3离线版地图
  10. python爬取股市数据