位置: 编程技术 - 正文

Yii2中组件的注册与创建方法

编辑:rootadmin

 今天本来打算研究一下yii2.0的AR模型的实现原理,然而,计划赶不上变化,突然就想先研究一下yii2.0的数据库组件创建的过程。通过对yii源码的学习,了解了yii组件注册与创建的过程,并发现原来yii组件注册之后并不是马上就去创建的,而是待到实际需要使用某个组件的时候再去创建对应的组件实例的。本文大概记录一下这个探索的过程。

  要了解yii组件的注册与创建,当然要从yii入口文件index.php说起了,整个文件代码如下:

可以看到入口文件引入了几个配置文件,并将所有配置文件的内容都合并到$config这个配置数组中,然后使用这个配置数组作为参数去创建一个应用实例。若将这个配置数组打印出来,就会看到,“components”下标对应的元素包含了yii组件的参数信息(这里只截图一小部分):

这些组件的信息是在引入进来的几个配置文件中配置的,Yii组件就是使用这些参数信息进行注册与创建的。

  接下来就进入yiiwebApplication类的实例化过程了,yiiwebApplication类没有构造函数,但是它继承了yiibaseApplication类:

所以会自动执行yiibaseApplication类的构造函数:

这里要顺便说一下预初始化方法preInit(),它的代码如下:

  这个函数对传递给构造函数的配置数组$config进行了一些预处理操作(这里省略了),最后使用coreComponents()方法返回的数组对$config数组进行了完善,coreComponents()方法是这样的:

  其实就是一些核心组件的配置,也就是说这些组件是可以不需要我们在配置文件中配置的,yii会自动进行注册。

  好了,回到yiibaseApplication类的构造函数,这个函数最后调用了yiibaseComponent类的构造函数,但yiibaseComponent类是没有构造函数的,不过它继承了yiibaseObject类:

所以也自动执行了yiibaseObject类的构造函数:

这里主要是调用了yiiBaseYii类的静态方法configure():

这个方法就是循环入口文件(new yiiwebApplication($config))->run();中的$config数组(这个数组的结构参见本文第一个截图),以数组键名作为对象属性名,对应的键值作为对象属性值进行赋值操作。所以当循环到组件配置参数的时候是这样子的:$object->components = $value($value为所有组件的配置数组),也就是对$object的components属性进行赋值操作,那这个$object是哪个类的对象呢?回想最初调用的源头,其实它就是入口文件中需要进行实例化的yiiwebApplication类的对象啊。然而,这个类和它的祖先类都没有components这个成员变量啊,不急,又要进行一番继承套路了,顺着yiiwebApplication类的继承关系一层一层往上找可以发现yiiwebApplication类最终也继承了yiibaseObject类,yiibaseObject类是支持属性的,所以yiiwebApplication类也支持属性(关于属性,可以参考我的另一篇博文:yii2之属性),当赋值操作找不到components成员变量时会调用setComponents()方法,又去找这个方法的所在,终于在它的祖先类yiidiServiceLocator中找到了setComponents()方法,没错,对应用实例的components属性进行赋值操作其实就是调用这个方法!

  好了,现在就来看看setComponents()这个方法到底干了啥:

其实很简单,就是循环各个组件的配置数组,调用set()方法,set()方法如下:

其实就是把组件配置存入$_definitions这个私有成员变量(即注册),然后呢?然后就没有下文了。。。

  搞了半天,原来yii创建应用实例的时候只是进行组件的注册,并没有实际创建组件,那么组件实例是什么时候进行创建的?在哪里进行创建的呢?别急。从上面推导的这个过程我们知道yiidiServiceLocator类是yiiwebApplication类的祖先类,所以其实yii的应用实例其实就是一个服务定位器,比如我们想访问数据库组件的时候,我们可以这样来访问:Yii::$app->db,这个Yii::$app就是yii应用实例,也就是yiiwebApplication类的实例,但是yiiwebApplication类和它的父类、祖先类都找不到db这个属性啊。哈哈,别忘了,php读取不到类属性的时候会调用魔术方法__get(),所以开始查找yiiwebApplication继承关系最近的祖先类中的__get()方法,最后在yiidiServiceLocator类中找到了,也就是说,Yii::$app->db最终会调用yiidiServiceLocator类中的__get()方法:

__get()方法首先调用has()方法(这个不再贴代码了)判断组件是否已注册,若已注册则调用get()方法:

其中私有成员变量$_components是存储已经创建的组件实例的,若发现组件已经创建过则直接返回组件示例,否则使用$_definitions中对应组件的注册信息,调用yiiBaseYii::createObject()方法进行组件创建,这个方法最终会调用依赖注入容器yiidiContainer的get()方法,接着就是依赖注入创建对象的过程了,关于这个过程已经在我的上一篇博文中讲解过了,可以参考一下:yii2之依赖注入与依赖注入容器。

  好了,yii组件注册与创建的整个过程就是这样的。最后总结一下,其实yii创建应用实例的时候只是进行了各个组件的注册,也就是将组件的配置信息存入yiidiServiceLocator类的私有成员变量$_definitions中,并没有进行实际创建,等到程序运行过程中真正需要使用到某个组件的时候才根据该组件在$_definitions中保存的注册信息使用依赖注入容器yiidiContainer进行组件实例的创建,然后把创建的实例存入私有成员变量$_components,这样下次访问相同组件的时候就可以直接返回组件实例,而不再需要执行创建过程了。yii的这个组件注册与创建机制其实是大有裨益的,试想一下,如果在应用实例创建的时候就进行所有组件的创建,将会大大增加应用实例创建的时间,用户每次刷新页面都会进行应用实例的创建的,也就是说用户每刷新一次页面都很慢,这用户体验就很不好了,而且很多情况下有很多组件其实是没有使用到的,但是我们还是花了不少时间去创建这些组件,这是很不明智的,所以yii的做法就是:先把组件参数信息保存起来,需要使用到哪些组件再去创建相应的实例,大大节省了应用创建的时间,同时也节省了内存,这种思路是很值得我们学习的!

总结

以上所述是小编给大家介绍的Yii2中组件的注册与创建方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对积木网网站的支持!

laravel开发中跨域的解决方案 前言众所周知我们大家在用laravel进行开发的时候,特别是前后端完全分离的时候,由于前端项目运行在自己机器的指定端口(也可能是其他人的机器),

Yii2使用驼峰命名的形式访问控制器的示例代码 yii2在使用的时候,访问控制器的时候,如果控制器的名称是驼峰命名法,那访问的url中要改成横线的形式。例如:publicfunctionactionRoomUpdate(){//}//访问的

ThinkPHP5邮件发送服务封装(可发附件) 本文实例为大家分享了ThinkPHP5封装邮件发送服务的具体代码,供大家参考,具体内容如下1.Composer安装phpmailercomposerrequirephpmailer/phpmailer2.ThinkPHP中封装邮

标签:

本文链接地址:https://www.jiuchutong.com/biancheng/274975.html 转载请保留说明!

上一篇:thinkPHP实现的验证码登录功能示例(thinkphp i方法)

下一篇:laravel开发中跨域的解决方案(laravel跨库查询)

  • 小微企业减半征收印花税代码
  • 小规模城建
  • 电商相对于传统企业有哪些特点?
  • 普通发票有没有有效期
  • 当月没有发生购销合同还要报印花税吗
  • 自建模具怎么做账
  • 个体工商户需要缴纳哪些税
  • 多付车款退回怎么做账
  • 由财政拨钱还银行借款怎么做分录?
  • 员工因为过错给公司造成损失
  • 营改增后房地产企业增值税税收筹划存在问题
  • 小规模纳税人一年不超过多少万
  • 企业如何处理
  • 起征点是什么意思举例子说明
  • 购买化妆品可以税前扣除吗
  • 河北省东光县是哪个城市
  • 个税按月算和按年算为什么不一样
  • 国债利息纳税调增还是减
  • 加盟费需要缴纳多少税
  • 电器供应
  • 税务部门实名认证
  • 出口报关单中有哪些内容
  • 协会收取会员单位的会务费怎么做账
  • 投资收益亏损后会怎么样
  • 车间购买办公用品
  • php制作一个表单
  • 蔚蓝的海怎么样
  • 使用的英文
  • 贝纳克波斯图干红葡萄酒
  • jar启动指定启动类
  • 个人独资企业建筑类怎么注册
  • 机动车组织机构代码查询
  • tsop封装
  • 税控盘全额抵扣发票怎么勾选
  • 引导式申报带出来的开票额与金税盘显示的不一致
  • 增值税的税目和税率
  • 关于非营利组织企业所得税免税收入问题的通知
  • 长期借款的主要缺点
  • python3 zipfile模块
  • 织梦cms怎么样
  • 定额的个体户怎么交税
  • 计提工资 个人所得税
  • 水泥贸易利润
  • 带有折扣的增值税专用发票图片
  • 固定资产属于净资产指的是什么
  • 关联公司代缴社保劳动者怎么处理
  • 高新技术企业进项税加计扣除10%如何填企业所得税季报
  • 银行转出去的账可以追回吗?
  • 利润表期初余额怎么填
  • 如何办理公司注册地址变更
  • 资产负债率怎么调整到50%以下
  • sql server 数学函数
  • mysql安装配置教程5.7.25
  • MySQL数据库常见的几种约束有哪些
  • CentOS 6.2(32位/64位) 安装步骤图文详解
  • windows下键盘不能用
  • win8硬盘占用100%
  • qqlogin.exe是什么进程 qqlogin.exe应用程序错误解决办法
  • win7右键没有
  • 如何将电脑的win7系统变为win10
  • win8切换输入法无效
  • win7怎么禁用软件
  • javascript的三种主要数据类型
  • kotlin开发教程
  • opengl gpu编程
  • jquery easyui 教程
  • re engine引擎
  • JavaScript弹出对话框
  • dns设置为网关会出现什么问题了
  • unity c++ dll
  • web.py 十分钟创建简易博客实现代码
  • bootstrap轮播效果
  • 外经证注销网上操作
  • 污水处理厂房产税优惠政策
  • 一般纳税人沙石税率是多少
  • 湖南电子税务局密码错误5次
  • 成都税务举报官网
  • 香水与香精有啥不一样
  • 外贸公司销售额可以10亿以上吗
  • 成都城镇居民社保怎么缴费
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设