当前位置: 首页 > 后端技术 > PHP

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

时间:2023-03-29 21:18:09 PHP

学习资料:Laravel底层核心代码解析核心概念Laravel(5.5.33)加载过程---实例方法服务容器与服务提供者服务容器ServiceContainnerServiceContainer通过依赖注入注册ServiceProvider提供给服务容器的能力。Laravel直接通过容器的实例化对象找到对应的服务,然后就可以直接使用它提供的能力。ServiceContainner是一个类的实例化对象。它在启动时加载所有可用的服务,然后在使用时解析并调用方法。ServiceProviderServiceProvider有能力提供服务的服务提供者//Laravel的服务提供者config/app.php'providers'=>[/**LaravelFrameworkServiceProviders...*///框架自带的ServiceProvider/**PackageServiceProviders...*///需要引入的ServiceProvider]Laravel源码解析服务容器$app/bootstrap/app.php$app=newIlluminate\Foundation\Application(realpath(__DIR__.'/../'));$app服务容器是Application类的实例化对象。src/Illuminate/Foundation/Application.phppublicfunction__construct($basePath=null){if($basePath){$this->setBasePath($basePath);//设置基本路径}$this->registerBaseBindings();//注册基础绑定$this->registerBaseServiceProviders();//注册基础服务提供者$this->registerCoreContainerAliases();//注册核心服务容器别名}注册基础绑定src/Illuminate/Foundation/Application.phpprotectedfunctionregisterBaseBindings(){static::setInstance($this);//自己实例化$this->instance('app',$this);//将app注册到instances数组$this->instance(Container::class,$this);//在实例数组中注册Container$this->singleton(Mix::class);$this->singleton(PackageManifest::class,function(){returnnewPackageManifest(newFilesystem,$this->basePath(),$this->getCachedPackagesPath());});}实例函数vendor/laravel/framework/src/Illuminate/Container/Container.php/***$abstract'app'$instanceApplication*$抽象容器er::class$instanceApplication*/publicfunctioninstance($abstract,$instance){$this->removeAbstractAlias($abstract);}//去掉抽象别名$isBound=$this->bound($abstract);//判断是否实例化unset($this->aliases[$abstract]);//删除别名//将实例添加到实例数组$this->instances[$abstract]=$instance;//如果之前有实例化就运行if($isBound){$this->rebound($abstract);}return$instance;}registerfunctionsrc/Illuminate/Foundation/Application.phpprotectedfunctionregisterBaseServiceProviders(){$this->register(newEventServiceProvider($this));$this->register(newLogServiceProvider($this));$this->register(newRoutingServiceProvider($this));}publicfunctionregister($provider,$options=[],$force=false){if(($registered=$this->getProvider($provider))&&!$force){返回$registered;}if(is_string($provider)){$provider=$this->resolveProvider($provider);}如果(方法_exists($provider,'register')){$provider->register();//调用ServiceProvider实例的register方法}//标记为已注册$this->markAsRegistered($provider);//判断App是否注册启动,如果创建则调用$provider的boot方法if($this->booted){$this->bootProvider($provider);}return$provider;}EventServiceProvider注册函数publicfunctionregister(){$this->app->singleton('events',function($app){return(newDispatcher($app))->setQueueResolver(function()使用($app){return$app->make(QueueFactoryContract::class);});});}singleton,bind,getClosure函数vendor/laravel/framework/src/Illuminate/Container/Container.php单例函数publicfunctionsingleton($abstract,$concrete=null){$this->bind($abstract,$concrete,true);}绑定函数publicfunctionbind($abstract,$concrete=null,$shared=false){//从实例和别名数组中删除$abstract$this->dropStaleInstances($abstract);如果(is_null($con克里特岛)){$具体=$抽象;}//如果$concrete不是匿名函数,将$concrete转换为匿名函数}//$abstract被添加到绑定数组$this->bindings[$abstract]=compact('concrete','shared');//如果抽象类型在这个容器中已经被解析过,我们会触发恢复监听监听器,这样任何一个解析过的对象都可以通过监听器回调更新对象的副本如果($this->resolved($abstract)){$this->rebound($abstract);}}getClosurefunction/***$abstractMix$concreteMix=>Closure*/protectedfunctiongetClosure($abstract,$concrete){返回函数($container,$parameters=[])使用($abstract,$concrete){if($abstract==$concrete){返回$container->build($concrete);}返回$container->make($concrete,$parameters);};}总结一下生成服务容器的过程:1.通过instance和register方法注册到instances数组2.通过singleton和bind方法绑定到bindings数组App.php基本流程实例化app(newIlluminate\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下的class参数映射到lluminate\Contracts\Http\Kernel::class类中的$app->singleton(Illuminate\Contracts\Http\Kernel::类,App\Http\Kernel::类);将App\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::班级);5.返回应用资源return$app;先创建ServiceProviderbind调用方法$abstract'events'//别名$concreteAnonymousfunction(作用是创建实例化对象)//比较自由,可以自由给属性赋值。第二个$abstract'Illuminate\Foundation\Mix'$concrete'Illuminate\Foundation\Mix'=>匿名函数第三个$abstract'Illuminate\Contracts\Http\Kernel::class'$concrete'App\Http\Kernel::class'=>anonymousfunction//只能实现构造函数中声明的属性和依赖结果:绑定到$this->bindings数组,并执行构造函数自定义ServiceProvider服务容器类(声明依赖)/Service/Family/FamilyService.php人=$人;$this->tv=$tv;echo'实例家庭服务';}publicfunctiontestPerson(){$this->persion->test();}}/服务/家庭/个人服务。phpapp->bind('Family','App\Service\Family\FamilyService');}配置别名/config/app.php'providers'=>[App\Providers\FamilyServiceProvider::class,]call//通过别名调用服务app('Family')->testPerson();//app()调用make()方法创建实例//通过服务名调用服务app('App\Service\Family\FamilyService')->testPerson();