xdebug分析php中的控制反转IOC、依赖注入DI、容器和后期静态绑定
概念
控制反转 IoC (Inversion of Control)
- 依赖关系的转移
- 依赖抽象而非实践
依赖注入 DI (Dependency Injection)
- 不必自己在代码中维护对象的依赖
- 容器自动根据配置,将依赖注入指定对象
容器(Container)
- 管理对象的生成、资源取得、销毁等生命周期
- 建立对象与对象之间的依赖关系
- 启动容器后,所有对象直接取用,不用编写任何一行代码来产生对象,或是建立对象之间的依赖关系。
后期静态绑定
- 后期绑定意思是,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。
- 也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。
分析代码
这里分析6份代码,需要参考 源码地址 php-oop 阅读
├── 1old.php #传统OOP
├── 2DI.php #依赖注入思想体现
├── 3DIC.php #依赖注入通过容器管理
├── 4IOC.php #简单的IOC容器
├── 5IOC_more.php #IOC的自动绑定绑定实现
├── 6static.php #后期静态绑定理解
1old.php 传统OOP写法
Foo的doSomething
包含对Bar的依赖,Bar也同样依赖Bim。
2DI.php DI思想写法
Foo和Bar初始化构建函数时private
存入对应的new的对象,foo调用doSomething
时通过this
层层传递。
3DIC.php 通过Container管理依赖
由Container
完成实例化、依赖管理的工作。
1.Container
通过__set
储存了对应的闭包匿名函数array
2.$c->foo
时开始通过__get
找到array
里的匿名函数进行实例化Foo
类,并执行__construct
3.doSomething
时调用具体class方法。
图中可以看到Container
通过__get
开始实例化三个closure闭包匿名函数。
4IOC.php DIC之静态绑定
1.开局bind
3个closure
匿名函数到registry
中
2.IoC::make('foo')
时通过“后期静态绑定”
3.找到foo的bind的匿名函数
4.$resolver()
实例化并_construct(IoC::make('bar'))
,重复2、3步骤初始化完成。
5.调用doSomething
方法,层层调用。
图中可以看到IoC::make
初始化3个类的并实例化_construct
了。
5IOC_more.php DIC特性之自动绑定(Autowiring)
这里只显示了99.7%的调用,隐藏了 :
Container->build
- 3x php::ReflectionClass->__construct
- 5x php::ReflectionClass->getConstructor
- 5x php::ReflectionClass->isInstantiable
等等,以免图片过长,有需要按源码地址可自行搭建查看。
1.开局与4IOC.php一样绑定匿名函数,直到__get
获取$foo = $c->foo
开始build
方法。
2.遇到Closure
闭包函数,执行new Foo($c->bar)
。
3.通过ReflectionClass
获得Bar
类的参数Bim
,使用newInstanceArgs
创建新类,并__construct
。
4.如果发现参数Bim
是个类,则递归解析,初始化完成。
5.调用doSomething
方法,层层调用。
6static.php 后期静态绑定
A::foo();
指定调用A的静态函数
parent::foo();
父级为A,A中的static运行计算到最高优先级为C(最后定义覆盖前面的)。
self::foo();
和上面一样,走到A的foo,static运行计算调用C的who,因为C重写了who方法。
参考:
https://segmentfault.com/a/1190000002424023#comment-area
https://www.kancloud.cn/martist/ma_zhao_liu/460380