IOC Container的工作机制和理解container 和Service Provider

WBOY
Release: 2016-06-20 12:27:25
Original
1047 people have browsed it

IOC Container的工作机制

做个测试:

app/Http/routes.php< ?phpclass Bar{}class Foo{    public $bar;    public function __construct( Bar $bar) //Foo这个class的构造函数里要传入Bar $bar,一层接着一层,一般情况下,我们需要不断的 new实例,解决所有的依赖                                           //但是laravel会帮你自动去解析和new实例化,很容易可以感觉到这是一种很大的便利。    {        $this->bar = $bar;    }}Route::get('/', function (Foo $foo) {  //这里其实不算是依赖注入,依赖注入是面向接口的,这里只是一个很像依赖注入的东西,这个就是laravel的IOC container                                        //laravel会尝试去解析Foo $foo这种语义,解析其实就是去查找是否有这样的class或者其他东西,有就会放到这里                                        //这里解析到这是一个Foo的class    dd($foo);});
Copy after login

其实这里laravel借用了php的反射

PHP5添加了一项新的功能:Reflection。这个功能使得phper可以reverse-engineer class, interface,function,method and extension。通过PHP代码,就可以得到某object的所有信息,并且可以和它交互。

反射是什么?

它是指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用。

再来看看binding

< ?phpclass Bar{}class Foo{    public $bar;    public function __construct( Bar $bar)    {        $this->bar = $bar;    }}App::bind('Foo',function(){   // laravel提供了bind的方法来注册binding,通过class或者interface名字(解析一起传递的闭包)来返回一个实例,功能上类似之前的自动查找和解析                              //不过如果使用了bind的话,那么会优先使用bind的方法,而不会再去自动查找和解析                              //这里就会先出现 “call here”    dd('call here');    return new Foo(new Bar());});Route::get('/', function (Foo $foo) {    dd($foo);});
Copy after login

laravel文档提到一个很重要的地方:Notice that we receive the container itself as an argument to the resolver. We can then use the container to resolve sub-dependencies of the object we are building.我们接收container,并且将他自身作为一个参数来解析,然后我们可以用来解析我们正在构建的对象的子依赖关系。相当于将依赖关系都交给container,我们只需要对container来做解析就好了。

详情参考: https://laravel.com/docs/5.2/container

理解container 和Service Provider

service provider服务提供者用于为相关服务容器提供统一绑定场所,此外服务提供者还可以做一些初始化启动操作。Laravel的每个核心组件都对应一个服务提供者,可以这么说,服务提供者是Laravel的心脏,是Laravel的核心,核心组件类在这里完成注册、初始化以供后续调用。

城堡、管家和奴隶

从前有一个城堡,这个城堡有个大管家,他管着一个干活的奴隶。

场景1.

城堡经营的不错,客人越来越多,大管家觉得城堡里应该有一种交通工具,方便大家出行。于是他去买了一匹马,交给了奴隶,并对奴隶说:

以后有客人需要交通工具的,就把这匹马交给他。

场景2.

城堡经营的越来越好,管家手里的钱多了,觉得马太慢了,骑着很不舒服。他又一次对奴隶说,下次有客人需要交通工具时,你去东方路上的奔驰4s店里,买一辆奔驰c级回来,交给客人。

场景3.

有一天,城堡里要接待一位外国政要,奔驰车级别不够了,得买劳斯莱斯,管家对奴隶说:如果这位政要需要出行,你就去买一辆劳斯莱斯回来,但是,不管他要求多少次,你都只能用那一辆,不能再买第二辆了(车太贵)。

这里的城堡对应的就是container,管家就是service provider,马、奔驰车、劳斯莱斯是service。

引用链接: http://jingpin.jikexueyuan.com/article/44059.html

这是官网文档service provider样例

< ?phpnamespace App\Providers;use Riak\Connection;use Illuminate\Support\ServiceProvider;class RiakServiceProvider extends ServiceProvider{    /**     * Register bindings in the container.     *     * @return void     */    public function register() //register方法是service provider独有的,固定语法    {        $this->app->singleton(Connection::class, function ($app) { //这里看到这个就是一个container的绑定写法,使用的是singleton方法,service provider管理container            return new Connection(config('riak'));                        });    }}
Copy after login

singleton方法

$this->app->singleton('FooBar', function ($app) {  //singleton方法会绑定一个class或者interface名字到一个container里,然后在随后的调用返回同一个实例    return new FooBar($app['SomethingElse']);     //这里绑定的是FooBar这个class的名,然后在这里返回了一个一样的FooBar实例});
Copy after login

然后我们看看laravel项目里的一个FilesystemServiceProvider.php provider来对比一下

vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemServiceProvider.php< ?phpnamespace Illuminate\Filesystem;use Illuminate\Support\ServiceProvider;class FilesystemServiceProvider extends ServiceProvider{    /**     * Register the service provider.     *     * @return void     */    public function register()  //一样是有register方法    {        $this->registerNativeFilesystem();  //调用了一个本地方法        $this->registerFlysystem();    }    /**     * Register the native filesystem implementation.     *     * @return void     */    protected function registerNativeFilesystem() //就是这个,而这个方法使用了singleton,绑定了一个files,但是返回的FileSystem名字却不是一样,                                                  //singleton其实是做了类似映射的处理,将files跟new Filesystem进行绑定关系,我们在访问files的时候就顺理成章地访问new Filesystem    {        $this->app->singleton('files', function () {              return new Filesystem;        });    }    省略..............
Copy after login

上面说了关于service provider,service provider本身其实相当于一个container的管理器,方便管理container,但本身没有什么操作性的东西,核心调用的还是container。所以再调回来说container,因为还不知道这个container自身是怎么使用的,

使用container的方式有几种,说使用其实就是解析container的名字来获取container的信息

$fooBar = $this->app->make('FooBar');  //用make方法,这个是属于container的make方法,make接受的参数是make(string $abstract, array $parameters = array()),                                      //主要用来从container中解析给定的信息,返回一个container的实例$fooBar = $this->app['FooBar']; //用传入数组的方法
Copy after login

这些使用方式可以通过查看源码来了解

vendor/laravel/framework/src/Illuminate/Foundation/helpers.phpif (! function_exists('app')) {    /**     * Get the available container instance.     *     * @param  string  $make     * @param  array   $parameters     * @return mixed|\Illuminate\Foundation\Application     */    function app($make = null, $parameters = [])    {        if (is_null($make)) {            return Container::getInstance();  //会返回一个container的实例        }        return Container::getInstance()->make($make, $parameters);    }}
Copy after login

引用参考: https://laravel.com/docs/5.2/container#resolving

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!