lumen容器模仿
<?php
class Container { private $bindings = [];
private $instances = []; public function getClosure($concrete) {
return function($parameter = []) use($concrete) { # 在这里我们找到了判断初始化函数的契机,利用反射我们可以做很多事,包括我们的问题
# 1.获得一个$concrete类反射
$reflector = new ReflectionClass($concrete);
# 2.判断这个类能否被实例化,例如 private function __construct(){}
if(!$reflector->isInstantiable()) {
throw new Exception("{$concrete} 无法被实例化");
} # 3.获取构造函数反射方法
$constructor = $reflector->getConstructor(); # 4.获取参数列表
$parameters = $constructor->getParameters(); # 5.遍历参数列表
$instancesParams = [];
foreach ($parameters as $_parameter) {
# 如果已经$parameter中已经设置了对应的参数
if(isset($parameter[$_parameter->name])) {
$instancesParams[] = $parameter[$_parameter->name];
continue;
} # 如果没设置判断一下这个参数是否存在默认值
if(!$_parameter->isDefaultValueAvailable()) {
throw new Exception("{$concrete} 无法被实例化,缺少参数{$_parameter->name}");
} $instancesParams[] = $_parameter->getDefaultValue();
} # 这里就需要通过反射来构建对象了
// return new $concrete($parameter);
return $reflector->newInstanceArgs($instancesParams);
};
} public function bind($abstract , $concrete=null, $shared = false)
{
if (is_null($concrete)) {
$concrete = $abstract;
} if (!$concrete instanceof Closure) {
$concrete = $this->getClosure($concrete);
} $this->bindings[$abstract] = [
'concrete' => $concrete,
'shared' => $shared
];
} public function make($abstract ,array $parameters = []) {
if (!isset($this->bindings[$abstract])) {
return false;
} if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
} # 先获取到具体的类型
$concrete = $this->bindings[$abstract]['concrete'];
# 这里需要思考一下
# 到目前为止我们的$this->bindings[$abstract]['concrete']里存储的都是通过getClosure方法生成的闭包。
# 那么直接在这里判断类型肯定行不通,所以我们跳到getClosure里面去看看
$object = $concrete($parameters);
if($this->bindings[$abstract]['shared']) {
$this->instances[$abstract] = $object;
} return $object;
}
} class Person{
private $name;
private $isProgrammer;
public function __construct($name,$isProgrammer = true) {
$this->name = $name;
$this->isProgrammer = $isProgrammer;
} public function me() {
$message = $this->isProgrammer ? ',Ta是一个程序员' :'';
return "姓名: {$this->name} $message";
}
}
$container = new Container();
$container->bind('Person',null,false);
$p1 = $container->make('Person',[
'name' => 'lilei',
'age'=>10
]); $p2 = $container->make('Person',[
'name' => 'zhangsan',
'age'=>10
]); echo $p1->me();
echo $p2->me(); var_dump($p1,$p2);
var_dump($p1 === $p2);
lumen容器模仿的更多相关文章
- lumen-ioc容器测试 (2)
lumen-ioc容器测试 (1) lumen-ioc容器测试 (2) lumen-ioc容器测试 (3) lumen-ioc容器测试 (4) lumen-ioc容器测试 (5) lumen-ioc容 ...
- Lumen开发:如何向 IoC 容器中添加自己定义的类
版权声明:本文为博主原创文章,未经博主允许不得转载. 先在起始文件bootstrap/app.php加上$app->register(App\Providers\User\UserService ...
- [转贴]从零开始学C++之STL(二):实现一个简单容器模板类Vec(模仿VC6.0 中 vector 的实现、vector 的容量capacity 增长问题)
首先,vector 在VC 2008 中的实现比较复杂,虽然vector 的声明跟VC6.0 是一致的,如下: C++ Code 1 2 template < class _Ty, cl ...
- Java入门记(四):容器关系的梳理(上)——Collection
目录 一.Collection及子类/接口容器继承关系 二.List 2.1 ArrayList 2.1.1 序列化的探讨 2.1.2 删除元素 2.1.3 调整大小 2.2 Vector和Stack ...
- 整合Servlet到Spring容器
有时在Spring(3.2.5)项目中,如果使用到Servlet,可能希望Servlet实例作为bean受Spring容器管理,这样也能自动注入其他需要的bean,查了下,发现只针对过滤器提供了代理类 ...
- Java集合容器简介
Java集合容器主要有以下几类: 1,内置容器:数组 2,list容器:Vetor,Stack,ArrayList,LinkedList, CopyOnWriteArrayList(1.5),Attr ...
- Swing 顶层容器
顶层容器值得是容纳其他容器的容器组件,包括JFrame类,JWindows类,JDialog类,JApplet等.Swing中的顶层容器类Swing提供三个顶层容器类:JFrame,JDialog和J ...
- Cocos2d-x中__Dictionary容器以及实例介绍
__Dictionary类在Cocos2d-x 2.x时代它就是CCDictionary类,它是模仿Objective-C中的NSDictionary类而设计的,通过引用计数管理内存.__Dictio ...
- Cocos2d-x中Vector<T>容器以及实例介绍
Vector<T> 是Cocos2d-x 3.x推出的列表容器,因此它所能容纳的是Ref及子类所创建的对象指针,其中的T是模板,表示能够放入到容器中的类型,在Cocos2d-x 3.x中T ...
随机推荐
- Vue 事件的高级使用方法
Vue 事件的高级使用方法 事件方法 在Vue中提供了4中事件监听方法,分别是: $on(event: string | Array, fn) $emit(event: string) $once(e ...
- Linux:使用SecureCRT来上传和下载文件
SecureCRT自带的有几种上传下载功能,SecureCRT下的文件传输协议有以下几种:ASCII.Xmodem.Ymodem.Zmodem. ASCII:这是最快的传输协议,但只能传送文本文件. ...
- html基础:css样式2
1.字体边框基本设置 <!--border边框:solid实线,red红色,1px粗--> <!--font-weight: bolder字体加粗 font-size:字体大小--& ...
- Linux常用的三种软件安装方式
一:Linux源码安装 1.解压源码包文件 源码包通常会使用tar工具归档然后使用gunzip或bzip2进行压缩,后缀格式会分别为.tar.gz与.tar.bz2,分别的解压方式: ...
- Spring源码解析 | 第一篇 :IntelliJ IDEA2019.3编译Spring5.3.x源码
前言 工欲善其事必先利其器.学习和深读Spring源码一个重要的前提:编译源码到我们的本地环境.这样方便我们在本地环境添加注释.断点追踪.查看类或接口的继承关系等等,更加高效的学习Spring源码.个 ...
- Java架构师方案—多数据源开发详解及原理(二)(附完整项目代码)
1. mybatis下数据源开发工作 2. 数据源与DAO的关系原理模型 3. 为什么要配置SqlSessionTemplate类的bean 4. 多数据源应用测试 1. mybatis下数据源开发工 ...
- 一篇文章说清楚TDengine的FQDN
TDengine2.0以后需要使用FQDN来进行访问.小朋友,你是否有很多小问号:什么是FQDN,为什么要配置FQDN,如何配置FQDN.我们今天来简单讲一下.心急的小伙伴,可以直接跳转到配置章节. ...
- Git+Gitlab+Ansible剧本实现一键部署动态网站(5)
项目前言 之前已经写了一篇关于git和ansible的博客<Git+Gitlab+Ansible剧本实现一键部署Nginx–技术流ken>.关于git,gitliab,ansible在我以 ...
- maven问题汇总
Failed to read artifact descriptor for xxx:jar 在MyEclipse中执行Maven的install命令时,报“Failed to read artifa ...
- kubernetes部署Percona XtraDB Cluster集群
PXC介绍 全称percona-xtradb-cluster,提供了MySQL高可用的一种实现方法.PXC集群以节点组成(推荐至少3节点,便于故障恢复),每个节点都是基于常规的 MySQL Serve ...