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

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

前面共同学习长安链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 { //增加新binding
			namedBinding.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.specifiedParameters
		if len(option.args) > 0 {
			for i, v := range option.args {
				args[i] = v
			}
		}
		oldArgs := b.specifiedParameters
		b.specifiedParameters = args
		defer 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还提供其他方法调用,逻辑比较清晰,大家可自行分析。

相关文章:

  • 前端工作小结33-确定需求报告
  • SpringMVC 01: SpringMVC + 第一个SpringMVC项目
  • js之原生ajax、Jquery-$.ajax、自定义ajax(post请求、get请求)
  • nginx调优参数整理总结
  • 【webrtc】初识mia服务器
  • 详解模板引擎一
  • 大数据框架介绍与实操
  • springboot网上课程教学授课网站java
  • springboot+vue+elementui二手手机销售商城网站
  • JVM虚拟机栈的五道面试题
  • qemu与gdb内核调试环境搭建
  • STM32CUBEMX开发GD32F303(13)----定时器TIM捕获PWM测量频率与占空比
  • Spark Structured Streaming - 1
  • 自动化测试中的验证码问题
  • 工具箱目录
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【笔记】你不知道的JS读书笔记——Promise
  • java8-模拟hadoop
  • JS数组方法汇总
  • magento 货币换算
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • SOFAMosn配置模型
  • vue-cli3搭建项目
  • zookeeper系列(七)实战分布式命名服务
  • 每天10道Java面试题,跟我走,offer有!
  • 漂亮刷新控件-iOS
  • 前端
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 正则表达式小结
  • 大数据全解:定义、价值及挑战
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​卜东波研究员:高观点下的少儿计算思维
  • #QT项目实战(天气预报)
  • #stm32整理(一)flash读写
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (编译到47%失败)to be deleted
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (三)docker:Dockerfile构建容器运行jar包
  • (十八)SpringBoot之发送QQ邮件
  • (顺序)容器的好伴侣 --- 容器适配器
  • (四)JPA - JQPL 实现增删改查
  • (转)菜鸟学数据库(三)——存储过程
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • (轉貼) UML中文FAQ (OO) (UML)
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .vimrc php,修改home目录下的.vimrc文件,vim配置php高亮显示
  • /boot 内存空间不够
  • ::before和::after 常见的用法
  • @Autowired @Resource @Qualifier的区别