lumen-ioc容器测试 (6)
问题四、我们现在遇到的问题是构建对象的时候需要明确构造函数的参数类型、数量。并且增加程序的透明度
# class Container# 复制上面的代码
class Person{
private $name;
public function __construct($param) {
$this->name = $param['name'] ?? 'unknown';
} public function getName() {
return $this->name;
}
}
我们上一个版本的解决方案显然不是很理想。我们不能要求每个类的构造函数都传一个$param数组,这样不透明也不现实
那么如果我们要这样使用一个容器呢?
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');
$p1 = $container->make('Person',[
'name' => 'lilei',
]);
echo $p1->me();
接下来我们来解决上述问题
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.遍历参数列表
$instances = [];
foreach ($parameters as $_parameter) {
# 如果已经$parameter中已经设置了对应的参数
if(isset($parameter[$_parameter->name])) {
$instances[] = $parameter[$_parameter->name];
continue;
}
# 如果没设置判断一下这个参数是否存在默认值
if(!$_parameter->isDefaultValueAvailable()) {
throw new Exception("{$concrete} 无法被实例化,缺少参数{$_parameter->name}");
}
$instances[] = $_parameter->getDefaultValue();
}
# 这里就需要通过反射来构建对象了
// return new $concrete($parameter);
return $reflector->newInstanceArgs($instances);
};
}
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');
$p1 = $container->make('Person',[
'name' => 'lilei',
]);
echo $p1->me();
lumen-ioc容器测试 (6)的更多相关文章
- lumen-ioc容器测试 (1)
lumen-ioc容器测试 (1) lumen-ioc容器测试 (2) lumen-ioc容器测试 (3) lumen-ioc容器测试 (4) lumen-ioc容器测试 (5) lumen-ioc容 ...
- 自定义模拟一个Spring IOC容器
一.模拟一个IOC容器: 介绍:现在,我们准备使用一个java project来模拟一个spring的IOC容器创建对象的方法,也就是不使用spring的jar自动帮助我们创建对象,而是通过自己手动书 ...
- Aoite 系列(02) - 超动感的 Ioc 容器
Aoite 系列(02) - 超动感的 Ioc 容器 Aoite 是一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案.Aoite.Ioc 是一套解决依赖的最佳实践. 说 ...
- AutoFac使用~IOC容器(DIP,IOC,DI)
#cnblogs_post_body h1 { background-color: #A5A5A5; color: white; padding: 5px } Autofac一款IOC容器,据说比Sp ...
- IOC容器特性注入第一篇:程序集反射查找
学习kooboo的框架发现它的注入容器方法比较特别,同样是利用MVC的注入点,但它是查找网站下面bin所有的DLL利用反射查找特性找到对应的服务注入到容器. 这样的好处很简单:完全可以不用关心IOC容 ...
- 对依赖倒置原则(DIP)及Ioc、DI、Ioc容器的一些理解
1.概述 所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体.简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模 ...
- IOC容器中bean的生命周期
一.Bean的生命周期 Spring IOC容器可以管理Bean的生命周期,允许在Bean生命周期的特定点执行定制的任务. Spring IOC容器对Bean的生命周期进行管理的过程如下: (1).通 ...
- IoC容器Autofac - Autofac + Asp.net MVC + EF Code First(转载)
转载地址:http://www.cnblogs.com/JustRun1983/archive/2013/03/28/2981645.html 有修改 Autofac通过Controller默认构造 ...
- TypeC一个微软开发的超简单.NET依赖注入/IoC容器
控制反转(IoC,Inversion of Control)是由Martin Fowler总结出来的一种设计模式,用来减少代码间的耦合.一般而言,控制反转分为依赖注入(Dependency Injec ...
- IoC 之 2.2 IoC 容器基本原理(贰)
2.2.1 IoC容器的概念 IoC容器就是具有依赖注入功能的容器,IoC容器负责实例化.定位.配置应用程序中的对象及建立这些对象间的依赖.应用程序无需直接在代码中new相关的对象,应用程序由IoC ...
随机推荐
- 设计模式也可以这么简单(7年开发老鸟PS注释总结)
设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结,其中最出名的当属 Gang of Four (GoF) 的分类了,他们将设计模式分类为 23 种经典的模式,根据用途我们又可以分为三大类,分 ...
- docker push出现denied: requested access to the resource is denied
今天想再 把本地的docker image 镜像push 到: https://hub.docker.com/ Step1: login : https://hub.docker.com/ [root ...
- python中多进程multiprocessing、多线程threading、线程池threadpool
浅显点理解:进程就是一个程序,里面的线程就是用来干活的,,,进程大,线程小 一.多线程threading 简单的单线程和多线程运行:一个参数时,后面要加逗号 步骤:for循环,相当于多个线程——t=t ...
- archaius(3) 配置管理器
基于上一节介绍的配置源,我们来继续了解配置管理器.配置源只是抽象了配置的获取来源,配置管理器是基于配置源的基础上对这些配置项进行管理.配置管理器的主要功能是将配置从目标位置加载到内存中,并且管理内存配 ...
- springboot中关于Long类型返回前端精度丢失问题处理
使用了HuTool这个雪花算法后,会出现丢失精度的问题 hutool算法使用地址 对于一些大的业务表,自增主键这里 接口层得注意下是否会产生大数值 设计接口的时候采用String类型. 在项目中,我们 ...
- Elasticsearch数据库 | Elasticsearch-7.5.0应用基础实战
Elasticsearch 是一个可用于分布式以及符合RESTful 风格的搜索和数据分析引擎.-- Elastic Stack 官网 关于Elasticsearch的"爱恨情仇" ...
- jquery全选,全不选,反选
前台 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.o ...
- Git入门教程,详解Git文件的四大状态
大家好,欢迎来到周一git专题. git clone 在上一篇文章当中我们聊了怎么在github当中创建一个属于自己的项目(repository),简称repo.除了建立自己的repo之外,我们更多的 ...
- 手把手撸套框架-Victory框架1.0 详解
目录 其实Victory框架1.0 在8月份就完成了,整个9月份都没有更新博客,主要还是因为松懈了. 所以,趁着国庆节的放假的时间把博客给更新一下,1.0总的来说算不得一个成熟的产品,但是拿来开发我们 ...
- Java知识系统回顾整理01基础06数组03排序
一.选择法排序 选择法排序的思路: 把第一位和其他所有的进行比较,只要比第一位小的,就换到第一个位置来 比较完后,第一位就是最小的 然后再从第二位和剩余的其他所有进行比较,只要比第二位小,就换到第二个 ...