202 Ioc 仿照laravel实现一个最简的ioc容器
2016-10-10 18:26
465 查看
今天感觉对ioc的掌握不是很好,所以决定实现一遍看看。
bind()
当然上面的new操作也可以用闭包来实现,一个效果,闭包的好处在于这里的new不会立刻执行
make()
有几个问题
所有服务要一个一个bind进去、能否根据配置文件自动bind
每次用make使用一个新服务都会重新new一次
组件无法注入依赖
(继续第三点)组件是否可以自动注入依赖?
是否可以绑定一个闭包而不是实例来实现延迟加载。
build
使用反射获取构造函数的依赖关系,并调用
getDependencies 实现
1.最基本的bind 和 make
容器类最少有两个方法,一个bind将类绑定容器中,一个
make从容器中取得这个类
bind()
$mysql = new mysql(); $Ioc::bind('db',$mysql);
当然上面的new操作也可以用闭包来实现,一个效果,闭包的好处在于这里的new不会立刻执行
$Ioc::bind('db',function($Ioc){ return new mysql(); });
make()
$mysql= Ioc::make('db');
2.最初版本的容器实现
根据上面的描述,那么最初的Ioc类差不多长这样,此处为了更加直白,所以本应该是static的方法被写成了动态<?php class Ioc{ function bind($alias,$concrete){ $this->$alias = $concrete; } function make($alias){ return $this->$alias; } }
有几个问题
所有服务要一个一个bind进去、能否根据配置文件自动bind
每次用make使用一个新服务都会重新new一次
组件无法注入依赖
(继续第三点)组件是否可以自动注入依赖?
是否可以绑定一个闭包而不是实例来实现延迟加载。
3.Ioc初始化时候就把所有服务bind进去
此处可以用配置文件的方法,此处为了简单直接将配置放在构造函数中class Ioc { public function __construct(){ //这了只写了一个服务 $services = [ 'db' => 'mysql' ]; foreach ($services as $alias => $concrete_name) { $concrete = new $concrete_name; $this->bind($alias,$concrete); } } function bind(){ ... //跟上面一样 } function make(){ ... //跟上面一样 } } class mysql { function __construct(){ echo "具体实现就不写了,这应该是个pdo的二次封装"; } } $Ioc = new Ioc(); $Ioc->make('db');
4.用闭包的方法重写bind方法
将$concrete处理成一个返回实例的闭包,并将ioc容器实例注入到每个闭包中。
function bind($abstract,$concrete,$share){ // $this->$alias = $concrete; if (! $concrete instanceof Closure) { $concrete = $this->getClosure($abstract,$concrete); } $this->bindings[$abstract] = compact('concrete','shared'); }! function getClosure($abstract,$concrete){ //$c为Ioc容器对象 return function($c) use ($abstract,$concrete){ $method = ($abstract == $concrete) ? 'build' : 'make'; return $c->$method($concrete); }; }
5.让组件内部可以使用容器的其他服务
重写make方法,判断是否符合
isBuildable的条件,要么
$concrete == $abstract,要么
$concrete本身已经是闭包,如果不符合那么则调用
build方法使之符合
isBuildable。
//生成实例对象 解决接口和实例化类之间依赖关系 public function make($abstract){ // return $this->$abstract; $concrete = $this->getConcrete($abstract); if ($this->isBuildable($concrete,$abstract)){ $object = $this->build($concrete); } else { $object = $this->make($concrete); } return $object; } public function isBuildable($concrete,$abstract){ return $concrete == $abstract || $concrete instanceof Closure; }
build
使用反射获取构造函数的依赖关系,并调用
getPendencies获取依赖实例。
public function build($concrete){ if ($concrete instanceof Closure){ //Ioc容器实例注入 return $concrete($this); } //反射对象 $reflector = new ReflectionClass($concrete); //检查这个类是否可实例化 if (!$reflector->isInstantiable()){ echo $message = "Target [$concrete] is not instantiable."; } $constructor = $reflector->getConstructor(); if (is_null($constructor)){ return new $constructor; } $dependencies = $constructor->getParameters(); $instances = $this->getPendencies($dependencies); return $reflector->newInstanceArgs($instances); }
getDependencies 实现
public function getDependencies($parameters){ $dependencies = []; foreach ($dependencies as $parameter) { $denpendency = $parameter->getClass(); if (is_null($denpendency)){ $denpendencies[] = NULL; } else { $dependencies[] = $this->resolveClass($parameter); } } return (array)$dependencies; } public function resolveClass(ReflectionParameter $parameter){ return $this->make($parameter->getClass()->name); }
6.将单例的服务单独bind
使用反射自动bind
使用facade
相关文章推荐
- 204 IOC 仿照laravel实现一个最简容器 2
- 仿照spring-boot实现一个简单的ioc容器(二)
- 仿照spring-boot实现一个简单的ioc容器(一)
- IoC原理-使用反射/Emit来实现一个最简单的IoC容器
- 深入理解Spring--动手实现一个简单的SpringIOC容器
- 【最简单IOC容器实现】实现一个最简单的IOC容器
- Spring实现一个简单的SpringIOC容器
- 1000行代码读懂Spring(一)- 实现一个基本的IoC容器
- 1000行代码读懂Spring- 实现一个基本的IoC容器
- 如何设计并实现一个ioc容器(转载)
- 简单实现一个laravelapp容器绑定实例
- 【最简单IOC容器实现】实现一个最简单的IOC容器
- 揣摩实现一个ioc容器需要做的事情
- 1000行代码读懂Spring(一)- 实现一个基本的IoC容器
- 深入理解Spring--动手实现一个简单的SpringIOC容器-注解版
- IoC原理-使用反射/Emit来实现一个最简单的IoC容器
- 自己实现一个IOC(控制翻转,DI依赖注入)容器
- 实现一个简易IOC容器
- 用java的spring实现一个简单的IOC容器示例代码
- 写一个自己的Spring框架——简单实现IoC容器功能