第十课 laravel服务容器及服务提供者介绍
服务容器:就是一个存放对象的空间
为什么使用容器?
IOC 控制反转 解决对象之间的依赖关系 的解耦 //降低代码之间的耦合度
控制反转的使用经常会和 DI 依赖注入一起实现。
Inversion of Control 控制反转
Dependency Injection DI 依赖注入,使用反射实现 。 使用容器中注册
laravel的容器是在哪里?

所有的服务提供者都会继承 ServiceProvides
绑定容器 谁来做? 由服务提供者来做
服务提供者:编写说明。
如果没有继承任何接口,或父类就无需要注册到容器,等使用的时候,直接使用依赖注入即可使用。
例如:
public function tt(\App\Services\StudentService $stu) {
echo $stu->eat();
}
就是我们编写的服务没有继承、或者实现任何的接口文件,就可以使用依赖注入了。
那么没有继承任何接口是在说什么呢?
//定义了一个接口文件
namespace App\Contracts;
interface PeopleContracts{
public function say;
public function eat;
}//学生服务类
namespace App\Services;
class StudentService extends ServiceProvides{
public function say(){
return '我是学生';
}
public function eat(){
return '每天去食堂吃饭';
}
}//农民服务类
namespace App\Services;
class FarmerProvider extends ServiceProvides{
puclic function say(){
return '我是工人';
}
public function eat(){
return '我每天都要自己做饭';
}
}服务类我们定义好了,那么如何注册到容器呢?
这其中有三种注册方法:
//单例模式
$this->app->singleton('People', function () {
return new App\Services\StudentService();
});
//动态
$this->app->bind('People', function () {
return new App\Services\StudentService();
});
//使用服务提供者进行绑定:
namespace App\Providers;
use App\Services\StudentService;
use Illuminate\Support\ServiceProvider;
class StudentProvider extends ServiceProvider{
public function boot(){
}
public function register(){
$this->app->singleton('People',function(){
return new StudentService();
});
}
}写好服务提供者后,在bootstrap/app.php 中 写入:
$app->register(App\Providers\StudentProvider::class);
=================================================
注意声明:在注册服务提供者的时候,首先会执行 register 方法,紧接着执行 boot() 方法,这是可据可查的。
服务提供者 register 这是首先要执行的方法,
再次boot 方法,其他自定义方法辅助这两个方法执行。
看下 src\Application.php 第180行
public function register($provider)
{
if (! $provider instanceof ServiceProvider) {
$provider = new $provider($this);
}
if (array_key_exists($providerName = get_class($provider), $this->loadedProviders)) {
return;
}
$this->loadedProviders[$providerName] = true;
//在这里判断了 register
if (method_exists($provider, 'register')) {
$provider->register();
}
//判断了boot 方法是否存在,如果存在就执行
if (method_exists($provider, 'boot')) {
return $this->call([$provider, 'boot']);
}
}-----------------------------------------
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class MyServiceProvider extends ServiceProvider
{
public function boot(){
info('MyProvider write log服务 启动之后'.date('Y-m-d H:i:s')).microtime();
}
public function register(){
info('hahahahhahahhahahah'.date('Y-m-d H:i:s')).microtime();
}
}-----------------------------------------
看看日志:
[2018-07-30 19:27:45] lumen.INFO: hahahahhahahhahahah2018-07-30 19:27:45
[2018-07-30 19:27:45] lumen.INFO: MyProvider write log服务 启动之后2018-07-30 19:27:45
==============================
如果准备采用延迟加载ServiceProvider时,严禁进行注册 middleware, route 等系列操作。
同时,更改 defer 属性值后,需要执行 php artisan clear-compiled 和 php artisan optimize 以更新 ServiceProvider 缓存。
服务提供者 注册服务的时候,有两个方法:
register 在所有的服务提供者提供服务之前注册
boot 在所有服务加载之后进行注册的
这两种方式都是可以执行的。
providers 里面有一个 defer 设置为true ,延迟加载。 当使用的时候才进行注册。
所有的服务都是在 config/app.php 中进行注册的。
里面有一个 providers 数组,在这个里面写就可以了。
当然了,还有一些是在框架中就定义好的。
例如: Illuminate\Foundation\Application 中的 registerCoreContainerAliases方法
public function registerCoreContainerAliases()
{
foreach ([
'app' => [self::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, \Psr\SimpleCache\CacheInterface::class],
'cache.psr6' => [\Symfony\Component\Cache\Adapter\Psr16Adapter::class, \Symfony\Component\Cache\Adapter\AdapterInterface::class, \Psr\Cache\CacheItemPoolInterface::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, \Illuminate\Database\ConnectionResolverInterface::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\Hashing\HashManager::class],
'hash.driver' => [\Illuminate\Contracts\Hashing\Hasher::class],
'translator' => [\Illuminate\Translation\Translator::class, \Illuminate\Contracts\Translation\Translator::class],
'log' => [\Illuminate\Log\LogManager::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],
] as $key => $aliases) {
foreach ($aliases as $alias) {
$this->alias($key, $alias);
}
}
}门面模式:
门面模式注册在哪里注册的呢? 在 config/app.php aliases 这样的一个数组
alias中注册所有的门面模式,里面一个 getFacadeAccessor 方法,方法里返回的字符串就是注册到容器中的服务名称,切记。
protected static function getFacadeAccessor()
{
return 'log';
}
服务提供者 provider
/**
* 获取提供商提供的服务
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [];
}