Laravel底层学习笔记02 - 服务容器,服务提供者

IT小马 -
Laravel底层学习笔记02 - 服务容器,服务提供者

学习资料:
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$concrectEventServiceProvider::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数组

app.php基本流程

实例化app (new Illuminate\Foundation\Application())
1.1 运行构造函数 __construct()

 1.1.1 设置基础路径 $this->setBasePath($basePath);
 1.1.2 创建并绑定基础服务容器(app,Container) $this->registerBaseBindings();
 1.1.3 注册基础服务提供者 $this->registerBaseServiceProviders();
 1.1.3 注册基础服务别名 $this->registerCoreContainerAliases();

把App\Http\Kernel::class类下的参数映射到lluminate\Contracts\Http\Kernel::class类中

$app->singleton(
 Illuminate\Contracts\Http\Kernel::class,
 App\Http\Kernel::class
);

把App\Console\Kernel::class类下的参数映射到Illuminate\Contracts\Console\Kernel::class类中

$app->singleton(
 Illuminate\Contracts\Console\Kernel::class,
 App\Console\Kernel::class
);

把App\Exceptions\Handler::class类下的参数映射到Illuminate\Contracts\Debug\ExceptionHandler::class类中

$app->singleton(
 Illuminate\Contracts\Debug\ExceptionHandler::class,
 App\Exceptions\Handler::class
);

5.返回app资源 return $app;

特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

php介绍

PHP即“超文本预处理器”,是一种通用开源脚本语言。PHP是在服务器端执行的脚本语言,与C语言类似,是常用的网站编程语言。PHP独特的语法混合了C、Java、Perl以及 PHP 自创的语法。利于学习,使用广泛,主要适用于Web开发领域。

Tags 标签

laravelphp

扩展阅读

加个好友,技术交流

1628738909466805.jpg