前面共同学习长安链ioc如何使用,下面聊聊IOC的实现原理。本节主要分析两个方法,RegisterResolve

1.func (c *Container) Register(constructor interface{}, options ...Option) error

第一个参数:constructor ,某实现的构造方法,例如:NewFileStore
第二个参数:Option,例如:InterfaceParametersDefault等,上节有介绍。

1) constructor参数必须是函数

    reflectedResolver := reflect.TypeOf(constructor)if reflectedResolver.Kind() != reflect.Func {return errors.New("container: the constructor must be a function")}

2)创建一个binding对象,用于设置构造方法 + 默认参数值

    b := &binding{constructor: constructor, specifiedParameters: make(map[int]interface{})}

3)设置Register参数,包括执行InterfaceParametersDefault等方法。

       for _, op := range options {err := op(b)if err != nil {return err}}

4)读取构造方法返回值类型,如果Register设置过container.Interface(),则container.Interface()的值(b.resolveTypes[i])作为构造方法的类型。

        resolveType := reflectedResolver.Out(i)if len(b.resolveTypes) > i && b.resolveTypes[i] != nil { //如果指定了映射的interface,则使用指定的if !resolveType.Implements(b.resolveTypes[i]) {return errors.New("resolve type " + resolveType.String() + " not implement " + b.resolveTypes[i].String())}resolveType = b.resolveTypes[i]}

5)以构造方法返回值类型为key,以binding方法为体将该结构存储到container下。如果该key存在过,则叠加存储;如果该key不存在,则创建。

     if namedBinding, has := c.bind[resolveType]; has { //增加新bindingnamedBinding.addNewBinding(b, b.isDefault)} else { //没有注册过这个接口的任何绑定c.bind[resolveType] = newNamedBinding(b)}

2.func (c *Container) Resolve(abstraction interface{}, options ...ResolveOption) error
前面Register方法把实现的构造方法、类型、参数记录到containerbind字段。
Resolve方法根据方法类型寻找匹配的bind字段,与abstraction 指针进行绑定。

1)设置Resolve参数,包括执行ArgumentsResolveName等方法。

       for _, op := range options {err := op(b)if err != nil {return err}}

2)abstraction 必须是指针

if receiverType.Kind() == reflect.Ptr {

3)从bind结构中找到匹配的接口类型

     elem := receiverType.Elem()b, err := c.getBinding(elem, option.name)if err != nil {return errors.New("resolve type: " + receiverType.String() + " no concrete found for: " + elem.String())}

4)根据Arguments获取构造方法的参数,替换Register传入的Parameters参数

     args := b.specifiedParametersif len(option.args) > 0 {for i, v := range option.args {args[i] = v}}oldArgs := b.specifiedParametersb.specifiedParameters = argsdefer func() {b.specifiedParameters = oldArgs}()

5)找到构造方法、也知道参数,调用该方法绑定实现对象

     instance, err := b.resolve(c)if err != nil {return err //errors.New("resolve type: " + receiverType.String() + " " + err.Error())}reflect.ValueOf(abstraction).Elem().Set(reflect.ValueOf(instance))

长安链ioc还提供其他方法调用,逻辑比较清晰,大家可自行分析。

长安链源码学习v2.2.1--ioc机制(十)相关推荐

  1. 长安链源码学习--提案(Proposer)(五)

    作者:明神特烦恼 公众号:明神特烦恼 提案一般是共识流程中第一步,后面步骤为多阶段的投票,最终达到一致.这里分析提案将独立于共识,分析如何生成待共识的消息.提案的高度信息.提案人确认等由其他共识模块传 ...

  2. DotText源码学习——ASP.NET的工作机制

    --本文是<项目驱动学习--DotText源码学习>系列的第一篇文章,在这之后会持续发表相关的文章. 概论 在阅读DotText源码之前,让我们首先了解一下ASP.NET的工作机制,可以使 ...

  3. Vue源码学习——v2.5.8

    1. cache util 利用闭包,每个调用cached函数的方法都会生成一个cache变量,在cache变量中做缓存 /*** Create a cached version of a pure ...

  4. Kubernetes调度器源码学习(三):Preempt抢占机制、调度失败与重试处理

    本文基于Kubernetes v1.22.4版本进行源码学习 5.Preempt抢占机制 当高优先级的Pod没有找到合适的节点时,调度器会尝试抢占低优先级的Pod的节点.抢占过程是将低优先级的Pod从 ...

  5. Opencascade源码学习之模型数据

    Opencascade源码学习之模型数据 1.模型数据 2.几何工具 1.插值和拟合 1.分析一组点 2.基本插值和近似 3.2D 插值 4.3D 插值 5.2D 拟合 6.3D 拟合 7.曲面拟合 ...

  6. ERNIE源码学习与实践:为超越ChatGPT打下技术基础!

    ★★★ 本文源自AlStudio社区精品项目,[点击此处]查看更多精品内容 >>> ERNIE学习与实践:为超越ChatGPT打下技术基础! ERNIE是BERT相爱相杀的好基友,由 ...

  7. 文心ERNIE源码学习与实践:为超越ChatGPT打下技术基础!

    ERNIE学习与实践:为超越ChatGPT打下技术基础! ERNIE是BERT相爱相杀的好基友,由ERNIE发展起来的文心大模型,是GPT3.0的强劲竞争对手,未来还会挑战ChatGPT的江湖地位! ...

  8. spring源码学习之路---深入AOP(终)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章和各位一起看了一下sp ...

  9. Promise源码学习(2)

    Promise源码学习(2) 本篇为上一篇源码学习(1)的补充,主要是来介绍Promise.all()和Promise.race()方法. 闲话少叙,进入正题 Promise.race() 首先来简单 ...

最新文章

  1. Zookeeper整理(一)- 写操作产生事件,写操作与Watcher对应关系
  2. linuxz指令大全
  3. ASP.NET Core 用户注册 - ASP.NET Core 基础教程 - 简单教程,简单编程
  4. java动态生成HTML文件
  5. 草根程序员进入BAT
  6. 浅析NDI 5(一)基于NDI 5如何打造全球NDI演播室?
  7. android gpu平板 推荐,性能强的不像话,最强安卓平板华为平板M6上手
  8. 想要提高自己的写作水平?吃透这篇文章就够了
  9. PDF怎么转长图?这些方法不妨了解一下
  10. (二)ArcGIS JS 加载动态地图服务
  11. 远程办公一段时间了,你(团队)进入状态没?
  12. ubuntu 安装方法 wubi
  13. 不定方程非负整数解个数
  14. 电力电子中的有源和无源
  15. Mac os下时间戳转换
  16. terminate called after throwing an instance of ‘c10::Error‘ chunk expects at least a 1-d tensor
  17. 信息学奥赛一本通 1256:献给阿尔吉侬的花束 | OpenJudge NOI 2.5 7218:献给阿尔吉侬的花束
  18. 4.2.3 标准编码
  19. 在mysql中通配符_mysql查询中通配符的使用
  20. ubuntu如何查看网卡名称_修改Ubuntu网卡名称

热门文章

  1. [经验分享] 覃超直播课学习笔记
  2. 关于单相变频电源及变频电路部分介绍
  3. GPS-NMEA解析代码
  4. 分享自己在uniapp开发中用的css样式
  5. 视频or音频转文字的处理方案
  6. C语言简单编程案例——(五)
  7. FreeSWITCH安装教程
  8. python3.6+PyQt5安装
  9. 【新手向】centOS 7 linux虚拟机联网具体步骤
  10. 大数据蓝皮书:解读中国大数据发展十大趋势