关于laravel:Laravel底层学习笔记02-服务容器服务提供者

30次阅读

共计 3970 个字符,预计需要花费 10 分钟才能阅读完成。

学习材料:
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 数组

正文完
 0