学习材料:
laravel底层外围代码剖析外围概念
Laravel (5.5.33) 加载过程---instance办法

服务容器和服务提供者

服务容器 ServiceContainner

ServiceContainner通过依赖注入将ServiceProvider提供的能力注册进服务容器外部。

Laravel间接通过容器的实例化对象,找到对应的服务,就能够间接应用其提供的能力了。

ServiceContainner就是一个类的实例化对象,启动时加载所有可用服务,用的时候再解析调用其中的办法。

服务提供者 ServiceProvider

有能力提供服务的服务提供者
//Laravel 的服务提供者 config/app.php'providers' => [    /*     * Laravel Framework Service Providers...     */      //框架自带 Service Provider        /*     * Package Service Providers...     */    //须要引入的 Service Provider]

Laravel源码解析

服务容器 $app

/bootstrap/app.php
$app = new Illuminate\Foundation\Application(    realpath(__DIR__.'/../'));

$app服务容器,就是Application类的实例化对象。

src/Illuminate/Foundation/Application.php
public function __construct($basePath = null){    if ($basePath) {        $this->setBasePath($basePath);//设置根底门路    }    $this->registerBaseBindings();//注册根底绑定    $this->registerBaseServiceProviders();//注册根底服务提供者    $this->registerCoreContainerAliases();//注册外围服务容器别名}

注册根底绑定

src/Illuminate/Foundation/Application.php
protected function registerBaseBindings(){    static::setInstance($this);//实例化本人    $this->instance('app', $this);//将app注册到instances数组中    $this->instance(Container::class, $this);//将Container注册到instances数组中    $this->singleton(Mix::class);    $this->singleton(PackageManifest::class, function () {        return new PackageManifest(            new Filesystem, $this->basePath(), $this->getCachedPackagesPath()        );    });}

instance函数

vendor/laravel/framework/src/Illuminate/Container/Container.php
/** * $abstract 'app'            $instance Application * $abstract Container::class $instance Application */public function instance($abstract, $instance){    $this->removeAbstractAlias($abstract); //删除形象别名    $isBound = $this->bound($abstract);//判断是否实例化    unset($this->aliases[$abstract]); //删除别名    //将实例退出instances数组    $this->instances[$abstract] = $instance;    //如果之前存在实例化 则运行    if ($isBound) {        $this->rebound($abstract);    }    return $instance;}

register函数

src/Illuminate/Foundation/Application.php
protected function registerBaseServiceProviders(){    $this->register(new EventServiceProvider($this));    $this->register(new LogServiceProvider($this));    $this->register(new RoutingServiceProvider($this));}public function register($provider, $options = [], $force = false){    if (($registered = $this->getProvider($provider)) && ! $force) {        return $registered;    }    if (is_string($provider)) {        $provider = $this->resolveProvider($provider);    }    if (method_exists($provider, 'register')) {        $provider->register();//调用ServiceProvider实例的register办法    }    //标记为已注册    $this->markAsRegistered($provider);    //判断App是否已启动,已创立则调用$provider的启动(boot)办法    if ($this->booted) {        $this->bootProvider($provider);    }    return $provider;}

EventServiceProvider中的register函数

public function register(){    $this->app->singleton('events', function ($app) {        return (new Dispatcher($app))->setQueueResolver(function () use ($app) {            return $app->make(QueueFactoryContract::class);        });    });}

singleton,bind,getClosure函数

vendor/laravel/framework/src/Illuminate/Container/Container.php

singleton函数

public function singleton($abstract, $concrete = null){    $this->bind($abstract, $concrete, true);}

bind函数

public function bind($abstract, $concrete = null, $shared = false){    //从instances和aliases数组中移除$abstract    $this->dropStaleInstances($abstract);        if (is_null($concrete)) {        $concrete = $abstract;    }    //如果$concrete不是匿名函数,则将$concrete转化为匿名函数    if (! $concrete instanceof Closure) {        $concrete = $this->getClosure($abstract, $concrete);    }    //$abstract退出bindings数组    $this->bindings[$abstract] = compact('concrete', 'shared');    //如果形象类型已在此容器中解析,咱们将触发复原侦听器,以便已解析的任何对象能够通过侦听器回调更新对象的正本。    if ($this->resolved($abstract)) {        $this->rebound($abstract);    }}

getClosure函数

/** *  $abstract Mix $concrete Mix => Closure */protected function getClosure($abstract, $concrete){    return function ($container, $parameters = []) use ($abstract, $concrete) {        if ($abstract == $concrete) {            return $container->build($concrete);        }        return $container->make($concrete, $parameters);    };}
调用bind办法的三种形式:
调用形式$abstract$concrect
EventServiceProvider::class - register()'events'匿名函数
$this->singleton(Mix::class);'Illuminate\Foundation\Mix''Illuminate\Foundation\Mix' => 匿名函数
$app->singleton(Illuminate\Contracts\Http\Kernel::class,App\Http\Kernel::class);'Illuminate\Contracts\Http\Kernel''App\Http\Kernel'

总结

生成服务容器的过程:
1.通过instance和register办法注册到instances数组
2.通过singleton和bind办法绑定到bindings数组