php 自动绑定di容器实现
<?php class Bim
{
public function doSth()
{
echo __METHOD__.PHP_EOL;
}
} class Bar
{
protected $bim; public function __construct(Bim $bim)
{
$this->bim = $bim;
} public function doSth()
{
$this->bim->doSth();
echo __METHOD__.PHP_EOL;
}
} class Bar2 extends Bar
{
protected $bim; public function doSth()
{
$this->bim->doSth();
echo __METHOD__.PHP_EOL;
}
} class Foo
{
private $bar; public function __construct(Bar $bar)
{
$this->bar = $bar;
} public function doSth()
{
$this->bar->doSth();
echo __METHOD__.PHP_EOL;
}
} class Container
{
private $s = []; public function __set($k, $c)
{
$this->s[$k] = $c;
} public function __get($k)
{
return $this->s[$k]($this);
}
} class Container2
{
private $s = []; public function __set($k, $c)
{
$this->s[$k] = $c;
} public function __get($k)
{
if (!$this->s[$k]) {
return false;
}
return $this->build($this->s[$k]);
} public function build($className)
{
if ($className instanceof Closure) {
return $className($this);
} try {
$reflector = new ReflectionClass($className);
} catch (\ReflectionException $e) {
echo $className.'类反射异常'.PHP_EOL;
echo $e->getMessage();
} #检查类是否可实例化, 排除抽象类abstract和对象接口interface
if (!$reflector->isInstantiable()) {
throw new Exception("Can't instantiate this.");
} $constructor = $reflector->getConstructor(); #如果没有构造函数, 直接实例化并返回
if (is_null($constructor)) {
return new $className;
} $parameters = $constructor->getParameters(); #递归解析构造函数的参数
$dependencies = $this->getDependencies($parameters); #创建一个类的新实例,给出的参数将传递到类的构造函数.
return $reflector->newInstanceArgs($dependencies);
} public function getDependencies($parameters)
{
$dependencies = []; foreach ($parameters as $parameter) {
$dependency = $parameter->getClass(); if (is_null($dependency)) {
$dependencies[] = $this->resolveNonClass($parameter);
} else {
#是一个类,递归解析
$className = lcfirst($dependency->name);
#先取出容器中绑定的类 否则自动绑定
if ($this->s[$className]) {
$dependencies[] = $this->$className;
} else {
$dependencies[] = $this->build($dependency->name);
}
}
} return $dependencies;
} public function resolveNonClass($parameter)
{
// 有默认值则返回默认值
if ($parameter->isDefaultValueAvailable()) {
return $parameter->getDefaultValue();
}
throw new Exception('I have no idea what to do here.');
}
} // 依赖注入模式
//$foo = new Foo(new Bar(new Bim())); #di模式
// $c = new Container();
// $c->bim = function() {
// return new Bim();
// };
// $c->bar = function($c) {
// return new Bar($c->bim);
// };
// $c->foo = function($c) {
// return new Foo($c->bar);
// }; #实现了自动绑定
#1向di中注册类
$c = new Container2();
$c->bim = 'Bim';
#$c->bar = 'Bar2'; #实现了自动绑定 如果没有注册类的化就按自动加载去寻找类
$c->foo = 'Foo';
// $c->bar = 'Bar';
// $c->foo = function ($c) {
// return new Foo($c->bar);
// };
// 从容器中取得Foo
$foo = $c->foo;
$foo->doSth();
参考:https://segmentfault.com/a/1190000002424023
php 自动绑定di容器实现的更多相关文章
- DI容器Ninject在管理接口和实现、基类和派生类并实现依赖注入方面的实例
当一个类依赖于另一个具体类的时候,这样很容易形成两者间的"强耦合"关系.我们通常根据具体类抽象出一个接口,然后让类来依赖这个接口,这样就形成了"松耦合"关系,有 ...
- DI 容器实务建议
整理一些有关使用 DI 容器的一些建议事项,主要的参考数据源是 Jimmy Board 的文章:Container Usage Guidelines. 1.容器设定 避免对同一个组件(DLL)重复扫描 ...
- 最新iOS 6 in Xcode4.5新特性——Storyboard和属性自动绑定
最新iOS 6 in Xcode4.5新特性编程之二(上)——Storyboard和属性自动绑定 从Xcode 4.3开始,Storyboard 就是iOS 5和iOS 6中令人兴奋的一个新特性,他将 ...
- EntityFramework Core 自动绑定模型映射
笔者最近在和同事共同开发项目时,需要从他们提供的包含数据库实体类型的类库中读取实体信息绑定到自己的项目中(但是都在同一个解决方案里),所以很直接的一种方式就是把项目中所有的实体都以 public Db ...
- net core体系-web应用程序-4net core2.0大白话带你入门-8asp.net core 内置DI容器(DependencyInjection,控制翻转)的一点小理解
asp.net core 内置DI容器的一点小理解 DI容器本质上是一个工厂,负责提供向它请求的类型的实例. .net core内置了一个轻量级的DI容器,方便开发人员面向接口编程和依赖倒置(IO ...
- asp.net core 内置DI容器的一点小理解
DI容器本质上是一个工厂,负责提供向它请求的类型的实例. .net core内置了一个轻量级的DI容器,方便开发人员面向接口编程和依赖倒置(IOC). 具体体现为Micorosoft.Extensio ...
- 解读超轻量级DI容器-Guice与Spring框架的区别【转载】
依赖注入,DI(Dependency Injection),它的作用自然不必多说,提及DI容器,例如spring,picoContainer,EJB容器等等,近日,google诞生了更轻巧的DI容器… ...
- 手动实现一个 IOC/DI 容器
第一章为源码解析. 第二章为实现一个简单的 IOC 容器. 第三章进阶 Spring 插件开发. 手动实现一个 IOC/DI 容器 上一篇文章里我们已经对 Spring 的源码有了一个大概的认识,对于 ...
- FlexiGrid 使用 全选、自动绑定
1.介绍 Flexigrid是一个类似于Ext Gird,但基于jQuery开发的Grid.它具有的功能包括:可以调整列宽,合并列标题,分页,排序,显示/隐藏表格等.Flexigrid显示的数据能够通 ...
随机推荐
- 转-HttpClient4.3 连接管理
转 http://www.yeetrack.com/?p=782 2.1.持久连接 两个主机建立连接的过程是很复杂的一个过程,涉及到多个数据包的交换,并且也很耗时间.Http连接需要的三次握手开销很大 ...
- css线性渐变--linear-gradient
使用css直接写渐变,对于现在而言,应该属于比价简单的一件事了,在一定程度上,扁平化的设计趋势的出现,减少了使用渐变色的场景,但是并不影响我们逐渐的熟悉线性渐变Linear-gradient的写法. ...
- SpringMVC的几种返回方式
package com.boventech.learning.controller; import java.util.HashMap; import java.util.Map; import or ...
- Android新组件CardView
Android L以后,新增了一个CardView组件,Google官方应用中有不少地方是使用卡片来展示信息,背后应该就是这个CardView. 使用CardView要引入单独的support包:co ...
- MSSQL 全表搜索 指定字符串
平时在在MSSql中查询数据的时候,想查找,某个字段在数据库中是否存在,并且查询出在哪个表中,哪个字段下面,在不知道的情况下,操作起来会很麻烦,然后就写了一个sql语句,使用起来感觉挺方便的.当然了, ...
- Centos minimal安装
Q:为什么要安装minimal版本?而不是完整版 A:因为它资源小啊 @ @ 怎么安装就不说了,网上资源大把,Centos7好像变化挺大,mysql都装不上,还是装6吧~ 1.安装完是不能联网的,解决 ...
- Python模拟实现Linux系统unix2dos功能
目标 1.Linux系统与windows系统文件系统换行符问题 2.实现unix文件转换成dos文件格式 1.Linux系统与windows系统文件系统换行符 •关于回车|换行的来历 在计算机还没有出 ...
- inux中shell截取字符串方法总结
shell中截取字符串的方法有很多中, ${expression}一共有9种使用方法. ${parameter:-word} ${parameter:=word} ${parameter:?word} ...
- Linux 设置定时任务crontab命令
1. crontab命令概念 crontab命令用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和执行. cron 系统调度进程. 可以使 ...
- spark转换集合为RDD
SparkContext可以通过parallelize把一个集合转换为RDD def main(args: Array[String]): Unit = { val conf = new SparkC ...