参考
https://laravelacademy.org/po...
https://laravelacademy.org/po...php
讲的都是1个概念.html
Ioc: 主对象依赖的某些对象原来在对象内部产生.如今把这个动做放到外面,好比Ioc容器,,IoC容器控制了对象生命周期,须要对象时,直接找容器,容器实例负责查找及建立依赖对象(也能够直接绑定已有对象的实例).laravel
DI 由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并不是为软件系统带来更多功能,而是为了提高组件重用的频率,并为系统搭建一个灵活、可扩展的平台, 这个平台就是基于IOC容器.数组
注入的原理是反射
,根据类名建立实例,或者是Clouse
,即闭包函数建立实例.闭包
因此容器须要知道它负责的对象如何建立,这就是bind(绑定建立实例的闭包函数)和instance(绑定已有实例)的做用.app
如何保存绑定大量对象?,就用array数组搞定:ide
#bind绑定后的binding数组: [ 'A\1': 返回new的闭包函数 or 具体实现类 or 类名 'A\2': 返回new的闭包函数 or 具体实现类 or 类名 ] #若是是`singleton`方法,实例存在instances数组,供下次使用. [ 'A\1': A\1实例, 'A\2': A\2实例 ]
有了绑定关系,剩下的就是如何解析实例了,函数build
,make
,resolve
等.函数
//container.php $concrete = $this->getConcrete($abstract); // We're ready to instantiate an instance of the concrete type registered for // the binding. This will instantiate the types, as well as resolve any of // its "nested" dependencies recursively until all have gotten resolved. if ($this->isBuildable($concrete, $abstract)) { //build $object = $this->build($concrete); } else { $object = $this->make($concrete); }
最终的核心动做在build
里, 若是concrete是closure,则调用产生,不然根据类名反射
产生该实例post
反射里应该是一颗递归树,由于class A的constructor参数里, 可能依赖B,B依赖C,D...ui
public function build($concrete) { //... if ($concrete instanceof Closure) { return $concrete($this, $this->getLastParameterOverride()); } try { $reflector = new ReflectionClass($concrete); } catch (ReflectionException $e) { throw new BindingResolutionException("Target class [$concrete] does not exist.", 0, $e); } //... }
bind的基本原理就这样了,而singleton是单例模式,生成的单例存储会先存储到instance数组.
全部类都这样手动bind,固然麻烦,因而就有service provider
.
先register Provider, 它会调用每一个Provider实例里的register和boot,完成具体的实例bind.
public function register($provider, $force = false) { if (($registered = $this->getProvider($provider)) && ! $force) { return $registered; } // If the given "provider" is a string, we will resolve it, passing in the // application instance automatically for the developer. This is simply // a more convenient way of specifying your service provider classes. if (is_string($provider)) { $provider = $this->resolveProvider($provider); } $provider->register(); // If there are bindings / singletons set as properties on the provider we // will spin through them and register them with the application, which // serves as a convenience layer while registering a lot of bindings. if (property_exists($provider, 'bindings')) { foreach ($provider->bindings as $key => $value) { $this->bind($key, $value); } } if (property_exists($provider, 'singletons')) { foreach ($provider->singletons as $key => $value) { $this->singleton($key, $value); } } $this->markAsRegistered($provider); // If the application has already booted, we will call this boot method on // the provider class so it has an opportunity to do its boot logic and // will be ready for any usage by this developer's application logic. if ($this->isBooted()) { $this->bootProvider($provider); } return $provider; }