Skip to content

源码阅读 - 初始 : (2) 初始化 App

加载机制

公共文件入口

public/index.php

bootstrap/autoload.php
自动加载机制
    vendor/autoload.php
    加载 composer 扩展包的自动加载机制
    storage/framework/compiled.php
    如果存在编译文件则加载编译文件
bootstrap/app.php
	创建 `$app` = new Illuminate\\Foundation\\Application
		注册基础绑定 registerBaseBindings
			实例化 app
			实例化 Illuminate\\Container\\Container
		注册基础服务绑定	registerBaseServiceProviders
			注册 事件绑定
			注册 路由绑定
		注册核心容器 alias 关联	registerCoreContainerAliases
	App\\Http\\Kernel
	App\\Console\\Kernel
	App\\Exceptions\\Handler
kernel 的处理
- 创建 `kernel`
- 创建 `response`
- 发出 `response`
- 终止 `kernel`

初始化 Application

根据指定的路径来初始化应用, 原始码

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

Illuminate/Foundation/Application::__construct()

php
// 1) 注册基本绑定
$this->registerBaseBindings();
// 2) 注册服务提供者
// 如果存在 register 方法, 则执行并且标记为已经注册过. 如果系统已经启动, 则直接运行 boot 方法
$this->registerBaseServiceProviders();
// 3) 注册核心 Alias
$this->registerCoreContainerAliases();

1) 注册基本绑定

php
# 1) 实例化 app
$this->instance('app', $this);
# 实例化 container => app
$this->instance(Container::class, $this);
# 2) 实例化 PackageManifest
$this->instance(PackageManifest::class, new PackageManifest(...));

1-1) 实例化 app

实例化 App[Application::instance()]

这里拿 ('app', $this) 为例子来阅读源码

php
// 移除抽象关联
$this->removeAbstractAlias($abstract);
// 确定给定的抽象类型是否已经绑定
// 已经设定 Alias
$isBound = $this->bound($abstract);
// 移除关联
unset($this->aliases[$abstract]);
// 检测此类型是否被绑定过, 如果已经绑定会重新触发绑定并且更新类
// 实例化 instances['app'] = $this
$this->instances[$abstract] = $instance;
// 重新绑定
if ($isBound) {
    $this->rebound($abstract);
    // 1) make -> alias (resolve)
    # $this->make($abstract)

    // 触发回调
    # foreach ($this->getReboundCallbacks($abstract) as $callback) {
    #     call_user_func($callback, $this, $instance);
    # }
}

1-2) 实例化 PackageManifest

2) 注册事件处理

php
// 注册事件处理器
$this->register(new EventServiceProvider($this));
// 注册日志服务
$this->register(new LogServiceProvider($this));
// 注册路由服务
$this->register(new RoutingServiceProvider($this));

2-1) Application::register() 方法

php
/* sample service providers
$this->serviceProviders = [
    Illuminate\\Events\\EventServiceProvider Object
    Illuminate\\Log\\LogServiceProvider Object
    Illuminate\\Routing\\RoutingServiceProvider Object
];
*/
// 获取注册的对象, 传递($provider) 可以是对象/字串
if (($registered = $this->getProvider($provider)) && ! $force) {
    return $registered;
}
// 如果给定的 provider 是字串, 则返回实例化的对象.
if (is_string($provider)) {
    $provider = $this->resolveProvider($provider);
    # new $provider($this)
}
// 检测给定的对象是否存在 register 方法, 存在则执行 register 方法并标注为已注册
if (method_exists($provider, 'register')) {
    $provider->register();
}
$this->markAsRegistered($provider);
// todo - 什么时候启动
// 如果应用已经启动, 我们便有机会启动 ServiceProvider 的 boot 逻辑, 便于开发者持续开发
if ($this->booted) {
    $this->bootProvider($provider);
    # 启动 boot 方法
    # if (method_exists($provider, 'boot')) {
    #     return $this->call([$provider, 'boot']);
    # }
}
return $provider;

2-2) EventServiceProvider

// 注册事件触发器, 并且配置队列执行
$this->app->singleton('events', function ($app) {
    return (new Dispatcher($app))->setQueueResolver(function () use ($app) {
        return $app->make(QueueFactoryContract::class);
    });
});

2-3) LogServiceProvider

// 注册日志
$this->app->singleton('log', function () {
    return $this->createLogger();
});

2-4) RoutingServiceProvider

// 注册路由
$this->registerRouter();
// url 生成
$this->registerUrlGenerator();
// 定向器
$this->registerRedirector();
// psr 请求
$this->registerPsrRequest();
// psr 响应
$this->registerPsrResponse();
// 响应工厂
$this->registerResponseFactory();
// 控制器触发器
$this->registerControllerDispatcher();

3) 注册 Alias

将指定的类和 app 示例做绑定

php
$allAlias = [
    'app'                  => [
    	\\Illuminate\\Foundation\\Application::class,
    	\\Illuminate\\Contracts\\Container\\Container::class,
    	\\Illuminate\\Contracts\\Foundation\\Application::class,
    	\\Psr\\Container\\ContainerInterface::class
    ],
    ...
    'view'                 => [
    	\\Illuminate\\View\\Factory::class,
    	\\Illuminate\\Contracts\\View\\Factory::class
    ],
];

foreach($allAlias = as $key => $aliases) {
    foreach ($aliases as $alias) {
        // key   : app
        // alias : Illuminate\\Foundation\\Application::class
        $this->alias($key, $alias);
    }
}

3-1) 系统 alias 项目

php
$alias = [
    'app'                  => [
    	\\Illuminate\\Foundation\\Application::class,
    	\\Illuminate\\Contracts\\Container\\Container::class,
    	\\Illuminate\\Contracts\\Foundation\\Application::class,
    	\\Psr\\Container\\ContainerInterface::class
    ],
    'auth'                 => [
    	\\Illuminate\\Auth\\AuthManager::class,
    	\\Illuminate\\Contracts\\Auth\\Factory::class
    ],
    'auth.driver'          => [
    	\\Illuminate\\Contracts\\Auth\\Guard::class
    ],
    'blade.compiler'       => [
    	\\Illuminate\\View\\Compilers\\BladeCompiler::class
    ],
    'cache'                => [
    	\\Illuminate\\Cache\\CacheManager::class,
    	\\Illuminate\\Contracts\\Cache\\Factory::class
    ],
    'cache.store'          => [
    	\\Illuminate\\Cache\\Repository::class,
    	\\Illuminate\\Contracts\\Cache\\Repository::class
    ],
    'config'               => [
    	\\Illuminate\\Config\\Repository::class,
    	\\Illuminate\\Contracts\\Config\\Repository::class
    ],
    'cookie'               => [
    	\\Illuminate\\Cookie\\CookieJar::class,
    	\\Illuminate\\Contracts\\Cookie\\Factory::class,
    	\\Illuminate\\Contracts\\Cookie\\QueueingFactory::class
    ],
    'encrypter'            => [
    	\\Illuminate\\Encryption\\Encrypter::class,
    	\\Illuminate\\Contracts\\Encryption\\Encrypter::class
    ],
    'db'                   => [
    	\\Illuminate\\Database\\DatabaseManager::class
    ],
    'db.connection'        => [
    	\\Illuminate\\Database\\Connection::class, \\Illuminate\\Database\\ConnectionInterface::class
    ],
    'events'               => [
    	\\Illuminate\\Events\\Dispatcher::class,
    	\\Illuminate\\Contracts\\Events\\Dispatcher::class
    ],
    'files'                => [
    	\\Illuminate\\Filesystem\\Filesystem::class
    ],
    'filesystem'           => [
    	\\Illuminate\\Filesystem\\FilesystemManager::class,
    	\\Illuminate\\Contracts\\Filesystem\\Factory::class
    ],
    'filesystem.disk'      => [
    	\\Illuminate\\Contracts\\Filesystem\\Filesystem::class
    ],
    'filesystem.cloud'     => [
    	\\Illuminate\\Contracts\\Filesystem\\Cloud::class
    ],
    'hash'                 => [
    	\\Illuminate\\Contracts\\Hashing\\Hasher::class
    ],
    'translator'           => [
    	\\Illuminate\\Translation\\Translator::class,
    	\\Illuminate\\Contracts\\Translation\\Translator::class
    ],
    'log'                  => [
    	\\Illuminate\\Log\\Writer::class,
    	\\Illuminate\\Contracts\\Logging\\Log::class, \\Psr\\Log\\LoggerInterface::class
    ],
    'mailer'               => [
    	\\Illuminate\\Mail\\Mailer::class,
    	\\Illuminate\\Contracts\\Mail\\Mailer::class,
    	\\Illuminate\\Contracts\\Mail\\MailQueue::class
    ],
    'auth.password'        => [
    	\\Illuminate\\Auth\\Passwords\\PasswordBrokerManager::class,
    	\\Illuminate\\Contracts\\Auth\\PasswordBrokerFactory::class
    ],
    'auth.password.broker' => [
    	\\Illuminate\\Auth\\Passwords\\PasswordBroker::class,
    	\\Illuminate\\Contracts\\Auth\\PasswordBroker::class
    ],
    'queue'                => [
    	\\Illuminate\\Queue\\QueueManager::class,
    	\\Illuminate\\Contracts\\Queue\\Factory::class,
    	\\Illuminate\\Contracts\\Queue\\Monitor::class
    ],
    'queue.connection'     => [
    	\\Illuminate\\Contracts\\Queue\\Queue::class
    ],
    'queue.failer'         => [
    	\\Illuminate\\Queue\\Failed\\FailedJobProviderInterface::class
    ],
    'redirect'             => [
    	\\Illuminate\\Routing\\Redirector::class
    ],
    'redis'                => [
    	\\Illuminate\\Redis\\RedisManager::class,
    	\\Illuminate\\Contracts\\Redis\\Factory::class
    ],
    'request'              => [
    	\\Illuminate\\Http\\Request::class, \\Symfony\\Component\\HttpFoundation\\Request::class
    ],
    'router'               => [
    	\\Illuminate\\Routing\\Router::class,
    	\\Illuminate\\Contracts\\Routing\\Registrar::class,
    	\\Illuminate\\Contracts\\Routing\\BindingRegistrar::class
    ],
    'session'              => [
    	\\Illuminate\\Session\\SessionManager::class
    ],
    'session.store'        => [
    	\\Illuminate\\Session\\Store::class,
    	\\Illuminate\\Contracts\\Session\\Session::class
    ],
    'url'                  => [
    	\\Illuminate\\Routing\\UrlGenerator::class,
    	\\Illuminate\\Contracts\\Routing\\UrlGenerator::class
    ],
    'validator'            => [
    	\\Illuminate\\Validation\\Factory::class,
    	\\Illuminate\\Contracts\\Validation\\Factory::class
    ],
    'view'                 => [
    	\\Illuminate\\View\\Factory::class,
    	\\Illuminate\\Contracts\\View\\Factory::class
    ],
];

3-2) alias 结果

php
/* $this->aliases = [
    [Illuminate\\Foundation\\Application] => app
    [Illuminate\\Contracts\\Container\\Container] => app
    [Illuminate\\Contracts\\Foundation\\Application] => app
    [Psr\\Container\\ContainerInterface] => app
    [Illuminate\\Auth\\AuthManager] => auth
    [Illuminate\\Contracts\\Auth\\Factory] => auth
    ...
]
*/

singleton Kernel 和异常处理

原始代码

step 01:singleton

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

step 02:bind

// 抽象类绑定到实体类
$this->bind($abstract, $concrete, true);

step 03:bind code

// 如果没有给定实体类型, 我们简单设置实体类型为虚拟类型, 在那之后
// 在此之后,将注册为共享的具体类型,而不需要在两个参数中强制声明它们的类
$this->dropStaleInstances($abstract);
if (is_null($concrete)) {
    $concrete = $abstract;
}
// 如果工厂不是闭包,这意味着它只是一个类名,它被绑定到这个容器中
// 我们把抽象类型包装在它自己的闭包中,以便在扩展时给我们更多的便利。
if (! $concrete instanceof Closure) {
    $concrete = $this->getClosure($abstract, $concrete);
}
$this->bindings[$abstract] = compact('concrete', 'shared');
// 如果这个类型已经存在, 我们触发重新绑定
if ($this->resolved($abstract)) {
    $this->rebound($abstract);
}

说明

创建时间: 2023-01-15 00:32:00 , 最后编辑于 2023-12-21 12:12:00