Laravel Kernel引導流程分析

Laravel Kernel引導流程分析

代碼展示

protected function sendRequestThroughRouter($request)
{# $this->app->instance('request', $request);# Facade::clearResolvedInstance('request');// 主要是這句代碼$this->bootstrap();# return (new Pipeline($this->app))#            ->send($request)#            ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)#            ->then($this->dispatchToRouter());
}
public function bootstrap()
{if (! $this->app->hasBeenBootstrapped()) {$this->app->bootstrapWith($this->bootstrappers());}
}
protected function bootstrappers()
{######################################################################$bootstrappers = [#    \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,#    \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,#    \Illuminate\Foundation\Bootstrap\HandleExceptions::class,      #    \Illuminate\Foundation\Bootstrap\RegisterFacades::class,#    \Illuminate\Foundation\Bootstrap\RegisterProviders::class,      #    \Illuminate\Foundation\Bootstrap\BootProviders::class,#];#####################################################################return $this->bootstrappers;
}
public function bootstrapWith(array $bootstrappers)
{$this->hasBeenBootstrapped = true;foreach ($bootstrappers as $bootstrapper) {$this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);$this->make($bootstrapper)->bootstrap($this);$this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);}
}

$this->make($bootstrapper)->bootstrap($this):會先創建$bootstrapper對象,在執行對象的引導方法,參數為應用對象

處理流程

  1. 加載并設置應用的系統環境變量(IlluminateFoundationBootstrapLoadEnvironmentVariables)

    public function bootstrap(Application $app)
    {// /var/www/laravel/bootstrap/cache/config.php 存在則直接返回if ($app->configurationIsCached()) {return;}$this->checkForSpecificEnvironmentFile($app);try {// 委托Dotenv來臨時設置此次請求的系統環境變量,默認傳參依次為'/var/www/laravel'和'.env'(new Dotenv($app->environmentPath(), $app->environmentFile()))->load();} catch (InvalidPathException $e) {//}
    }
    protected function checkForSpecificEnvironmentFile($app)
    {// cli模式下,并且存在--env參數(類似命令為: cammond --env=example)if (php_sapi_name() == 'cli' && with($input = new ArgvInput)->hasParameterOption('--env')) {// 將系統環境文件(類似:/var/www/laravel/.env.example)設置為$app應用的environmentFile屬性,供后面使用$this->setEnvironmentFilePath($app, $app->environmentFile().'.'.$input->getParameterOption('--env'));}if (! env('APP_ENV')) {return;}$this->setEnvironmentFilePath($app, $app->environmentFile().'.'.env('APP_ENV'));
    }
    

    (new Dotenv($app->environmentPath(), $app->environmentFile()))->load()

    public function __construct($path, $file = '.env')
    {// 類似/var/www/laravel/.env$this->filePath = $this->getFilePath($path, $file);// 創建加載器,委托Loader處理$this->loader = new Loader($this->filePath, true);
    }
    protected function getFilePath($path, $file)
    {if (!is_string($file)) {$file = '.env';}$filePath = rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file;return $filePath;
    }
    public function load()
    {return $this->loadData();
    }
    protected function loadData($overload = false)
    {$this->loader = new Loader($this->filePath, !$overload);return $this->loader->load();
    }
    

    new Loader($this->filePath, !$overload)

    public function __construct($filePath, $immutable = false)
    {$this->filePath = $filePath;$this->immutable = $immutable;
    }
    public function load()
    {$this->ensureFileIsReadable();$filePath = $this->filePath;$lines = $this->readLinesFromFile($filePath);foreach ($lines as $line) {// 如果行不是注釋行且含有=號,則進行if (!$this->isComment($line) && $this->looksLikeSetter($line)) {$this->setEnvironmentVariable($line);}}return $lines;
    }
    // 將文件按行的形式讀入到數組并返回
    protected function readLinesFromFile($filePath)
    {$autodetect = ini_get('auto_detect_line_endings');ini_set('auto_detect_line_endings', '1');$lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);ini_set('auto_detect_line_endings', $autodetect);return $lines;
    }
    public function setEnvironmentVariable($name, $value = null)
    {// 檢測過濾校驗環境變量list($name, $value) = $this->normaliseEnvironmentVariable($name, $value);// 當immutable為真時,不覆蓋對應的環境變量if ($this->immutable && $this->getEnvironmentVariable($name) !== null) {return;}// apache運行環境下,嘗試臨時覆蓋系統環境變量if (function_exists('apache_getenv') && function_exists('apache_setenv') && apache_getenv($name)) {apache_setenv($name, $value);}// 嘗試臨時設置當前請求的系統環境變量if (function_exists('putenv')) {putenv("$name=$value");}// 賦值全局變量$_ENV[$name] = $value;$_SERVER[$name] = $value;
    }
    
  2. 將應用配置文件目錄(/var/www/laravel/config)下所有php文件返回的數組載入到$config對象(IlluminateFoundationBootstrapLoadConfiguration)

    public function bootstrap(Application $app)
    {$items = [];// /var/www/laravel/bootstrap/cache/config.php文件[配置文件的緩存合集,加快加載速度]存在則載入,并標記已加載if (file_exists($cached = $app->getCachedConfigPath())) {$items = require $cached;$loadedFromCache = true;}// 構建config對象,并注入到服務容器$app->instance('config', $config = new Repository($items));if (! isset($loadedFromCache)) {// 將系統的配置文件載入到$config對象$this->loadConfigurationFiles($app, $config);}// 設置$this['env']為系統環境變量app.env,沒有則默認為production$app->detectEnvironment(function () use ($config) {return $config->get('app.env', 'production');});date_default_timezone_set($config->get('app.timezone', 'UTC'));mb_internal_encoding('UTF-8');
    }$config = new \Illuminate\Config\Repository($items)
    public function __construct(array $items = [])
    {$this->items = $items;
    }protected function loadConfigurationFiles(Application $app, RepositoryContract $repository)
    {foreach ($this->getConfigurationFiles($app) as $key => $path) {// 此操作將在$repository對象里面構造一個多維數組屬性$this->items,值為相應的系統配置文件返回的數組,后續可以直接通過get獲取$repository->set($key, require $path);}
    }
    /** $files數組形式如下['app' => '/var/www/laravel/config/app.php','auth' => '/var/www/laravel/config/auth.php','xx.file' => '/var/www/laravel/config/xx/file.php','xx.yy.file' => '/var/www/laravel/config/xx/yy/file.php',]
    */
    protected function getConfigurationFiles(Application $app)
    {$files = [];// 系統配置文件的路徑(/var/www/laravel/config)$configPath = realpath($app->configPath());// 文件相關的操作委托給Finder類(很強大)來處理,Finder實現了IteratorAggregate的getIterator方法foreach (Finder::create()->files()->name('*.php')->in($configPath) as $file) {// 迭代/var/www/laravel/config下面嵌套的層層子目錄構造成.形式的目錄$directory = $this->getNestedDirectory($file, $configPath);$files[$directory.basename($file->getRealPath(), '.php')] = $file->getRealPath();}return $files;
    }$repository->set($key, require $path)
    // 構造將.形式轉變為相應層級的數組$this->items。比如:$key='xx.yy.file',$value='/var/www/laravel/config/xx/yy/file.php',將會構建為:$this->items['xx']['yy']['file'] = $value返回的數組。
    public function set($key, $value = null)
    {$keys = is_array($key) ? $key : [$key => $value];foreach ($keys as $key => $value) {Arr::set($this->items, $key, $value);}
    }
    

    根據默認的系統配置文件目錄,以上操作的結果如下:
    $config對象(new Repository)里面的$this->items數組屬性,后期可以通過$config->get()來獲取

    $this->items['app'] = /var/www/laravel/config/app.php返回的數組;
    $this->items['auth'] = /var/www/laravel/config/auth.php返回的數組;
    $this->items['broadcasting'] = /var/www/laravel/config/broadcasting.php返回的數組;
    $this->items['cache'] = /var/www/laravel/config/cache.php返回的數組;
    $this->items['database'] = /var/www/laravel/config/database.php返回的數組;
    $this->items['filesystems'] = /var/www/laravel/config/filesystems.php返回的數組;
    $this->items['mail'] = /var/www/laravel/config/mail.php返回的數組;
    $this->items['queue'] = /var/www/laravel/config/queue.php返回的數組;
    $this->items['services'] = /var/www/laravel/config/services.php返回的數組;
    $this->items['session'] = /var/www/laravel/config/session.php返回的數組;
    $this->items['view'] = /var/www/laravel/config/view.php返回的數組;假如有這樣的文件(/var/www/laravel/config/xx/yy/zz/file.php),返回['a'=>'hello,world!']數組
    將得到:$this->items['xx']['yy']['zz']['file'] = ['a'=>'hello,world!'];
    獲取方式: $config->get('xx.yy.zz.file.a', $default),直接返回'hello,world!';
    
  3. 設置應用的錯誤異常等處理事件(IlluminateFoundationBootstrapHandleExceptions)

    public function bootstrap(Application $app)
    {$this->app = $app;error_reporting(-1);set_error_handler([$this, 'handleError']);set_exception_handler([$this, 'handleException']);register_shutdown_function([$this, 'handleShutdown']);if (! $app->environment('testing')) {ini_set('display_errors', 'Off');}
    }
    public function handleError($level, $message, $file = '', $line = 0, $context = [])
    {if (error_reporting() & $level) {throw new ErrorException($message, 0, $level, $file, $line);}
    }
    public function handleException($e)
    {if (! $e instanceof Exception) {$e = new FatalThrowableError($e);}$this->getExceptionHandler()->report($e);if ($this->app->runningInConsole()) {$this->renderForConsole($e);} else {$this->renderHttpResponse($e);}
    }
    // 核心代碼,獲取的\App\Exceptions\Handle對象
    protected function getExceptionHandler()
    {// make時將會直接調用$this->bindings['Illuminate\Contracts\Debug\ExceptionHandler']['concrete'](此代碼位于/var/www/laravel/bootstrap/app.php,應用對象化后,直接注入到服務容器的幾個單例),返回\App\Exceptions\Handle對象,并將此對象注入到服務容器[參考]return $this->app->make(ExceptionHandler::class);
    }
    protected function renderHttpResponse(Exception $e)
    {$this->getExceptionHandler()->render($this->app['request'], $e)->send();
    }
    // \App\Exceptions\Handle
    public function render($request, Exception $e)
    {$e = $this->prepareException($e);if ($e instanceof HttpResponseException) {return $e->getResponse();} elseif ($e instanceof AuthenticationException) {return $this->unauthenticated($request, $e);} elseif ($e instanceof ValidationException) {return $this->convertValidationExceptionToResponse($e, $request);}return $this->prepareResponse($request, $e);
    }
    protected function renderHttpException(HttpException $e)
    {$status = $e->getStatusCode();view()->replaceNamespace('errors', [resource_path('views/errors'),__DIR__.'/views',]);if (view()->exists("errors::{$status}")) {return response()->view("errors::{$status}", ['exception' => $e], $status, $e->getHeaders());} else {return $this->convertExceptionToResponse($e);}
    }
    public function handleShutdown()
    {if (! is_null($error = error_get_last()) && $this->isFatal($error['type'])) {$this->handleException($this->fatalExceptionFromError($error, 0));}
    }
    
  4. 根據配置項設置應用的 Facades(IlluminateFoundationBootstrapRegisterFacades)

    public function bootstrap(Application $app)
    {Facade::clearResolvedInstances();Facade::setFacadeApplication($app);// 將配置文件/var/www/laravel/config/app.php返回數組的鍵為aliases的值賦給\Illuminate\Foundation\AliasLoader的aliases屬性,并進行注冊AliasLoader::getInstance($app->make('config')->get('app.aliases', []))->register();
    }
    public static function clearResolvedInstances()
    {static::$resolvedInstance = [];
    }
    public static function setFacadeApplication($app)
    {static::$app = $app;
    }\Illuminate\Foundation\AliasLoader
    public static function getInstance(array $aliases = [])
    {if (is_null(static::$instance)) {return static::$instance = new static($aliases);}$aliases = array_merge(static::$instance->getAliases(), $aliases);static::$instance->setAliases($aliases);return static::$instance;
    }
    private function __construct($aliases)
    {$this->aliases = $aliases;
    }
    public function getAliases()
    {return $this->aliases;
    }
    public function setAliases(array $aliases)
    {$this->aliases = $aliases;
    }
    public function register()
    {if (! $this->registered) {$this->prependToLoaderStack();$this->registered = true;}
    }
    protected function prependToLoaderStack()
    {// 將$this->load注冊到自動加載器的最前面,失敗時拋異常spl_autoload_register([$this, 'load'], true, true);
    }
    public function load($alias)
    {// $facadeNamespace = 'Facades\\',估計是框架內部使用的,以后再看吧if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) {$this->loadFacade($alias);return true;}if (isset($this->aliases[$alias])) {return class_alias($this->aliases[$alias], $alias);}
    }
    

    Facade的本質

    實際上是通過$app->make('config')->get('app.aliases', [])取出config/app.php文件里面的aliases數組并實例化AliasLoader,再將AliasLoader->load方法放到spl自動加載器最前面,最后通過class_alias($this->aliases[$alias], $alias)。當調用Cache::Method時,會觸發Facdes的__callStatic魔術方法,此方法會調用相應對象里面的方法。

  5. 注入配置項的服務提供者(IlluminateFoundationBootstrapRegisterProviders)

    public function bootstrap(Application $app)
    {$app->registerConfiguredProviders();
    }
    public function registerConfiguredProviders()
    {(new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))->load($this->config['app.providers']);
    }
    public function getCachedServicesPath()
    {return $this->bootstrapPath().'/cache/services.php';
    }// 先取services緩存文件,再對\Illuminate\Foundation\ProviderRepository進行實例化,隨后加載系統配置文件(./config/app.php)里面的providers數組
    (new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))->load($this->config['app.providers'])
    public function __construct(ApplicationContract $app, Filesystem $files, $manifestPath)
    {$this->app = $app;$this->files = $files;$this->manifestPath = $manifestPath;
    }
    public function load(array $providers)
    {$manifest = $this->loadManifest();if ($this->shouldRecompile($manifest, $providers)) {$manifest = $this->compileManifest($providers);}foreach ($manifest['when'] as $provider => $events) {$this->registerLoadEvents($provider, $events);}foreach ($manifest['eager'] as $provider) {// 直接注冊服務(將直接調用服務的register方法)$this->app->register($provider);}$this->app->addDeferredServices($manifest['deferred']);
    }
    public function loadManifest()
    {if ($this->files->exists($this->manifestPath)) {$manifest = $this->files->getRequire($this->manifestPath);if ($manifest) {return array_merge(['when' => []], $manifest);}}
    }
    public function shouldRecompile($manifest, $providers)
    {return is_null($manifest) || $manifest['providers'] != $providers;
    }
    protected function compileManifest($providers)
    {$manifest = $this->freshManifest($providers);foreach ($providers as $provider) {$instance = $this->createProvider($provider);// 延遲加載的服務if ($instance->isDeferred()) {foreach ($instance->provides() as $service) {$manifest['deferred'][$service] = $provider;}// 注冊延遲的事件$manifest['when'][$provider] = $instance->when();}// 即時加載的服務else {$manifest['eager'][] = $provider;}}return $this->writeManifest($manifest);
    }
    protected function freshManifest(array $providers)
    {return ['providers' => $providers, 'eager' => [], 'deferred' => []];
    }
    public function createProvider($provider)
    {return new $provider($this->app);
    }
    public function isDeferred()
    {return $this->defer;
    }
    public function writeManifest($manifest)
    {if (! is_writable(dirname($this->manifestPath))) {throw new Exception('The bootstrap/cache directory must be present and writable.');}$this->files->put($this->manifestPath, '<?php return '.var_export($manifest, true).';');return array_merge(['when' => []], $manifest);
    }
    protected function registerLoadEvents($provider, array $events)
    {if (count($events) < 1) {return;}$this->app->make('events')->listen($events, function () use ($provider) {$this->app->register($provider);});
    }
    public function addDeferredServices(array $services)
    {$this->deferredServices = array_merge($this->deferredServices, $services);
    }
    

    大致流程

    通過/var/www/laravel/bootstrap/cache/services.php等實例化IlluminateFoundationProviderRepository,并加載$this->config['app.providers']數組。實例化app.providers各服務提供者,根據其defer屬性將服務進行分類(延遲服務|即時服務),從而得到一個$manifest數組(格式如services.php,延遲處理:deferred=>注冊延遲的服務,以后再進行調用;when=>注冊延遲的事件;即時處理:eager=>直接進行注冊調用等),并重新寫入到services.php,然后根據此文件進行相應的處理。

  6. 啟動服務提供者的boot方法等操作(IlluminateFoundationBootstrapBootProviders)

    public function bootstrap(Application $app)
    {$app->boot();
    }
    public function boot()
    {if ($this->booted) {return;}// 可以通過應用的booting方法來注冊服務啟動前的事件監聽者$this->fireAppCallbacks($this->bootingCallbacks);// 嘗試調用所有的服務提供者的boot方法array_walk($this->serviceProviders, function ($p) {$this->bootProvider($p);});$this->booted = true;// 可以通過應用的booted方法來注冊服務啟動后的事件監聽者,若已經啟用了,則直接出發事件$this->fireAppCallbacks($this->bootedCallbacks);
    }
    protected function fireAppCallbacks(array $callbacks)
    {foreach ($callbacks as $callback) {call_user_func($callback, $this);}
    }
    protected function bootProvider(ServiceProvider $provider)
    {if (method_exists($provider, 'boot')) {return $this->call([$provider, 'boot']);}
    }

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/396352.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/396352.shtml
英文地址,請注明出處:http://en.pswp.cn/news/396352.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android RecyclerView (一) 使用完全解析

轉載請標明出處&#xff1a; http://blog.csdn.net/lmj623565791/article/details/45059587&#xff1b; 本文出自:【張鴻洋的博客】 概述 RecyclerView出現已經有一段時間了&#xff0c;相信大家肯定不陌生了&#xff0c;大家可以通過導入support-v7對其進行使用。 據官方的…

數據透視表日期怎么選范圍_透視范圍

數據透視表日期怎么選范圍by Tiffany White蒂芙尼懷特(Tiffany White) 透視范圍 (Putting Scope in Perspective) In JavaScript, lexical scope deals with where your variables are defined, and how they will be accessible — or not accessible — to the rest of your…

feign調用多個服務_Spring Cloud 快速入門系列之feign–微服務之間的調用

我們將一個大的應用拆成多個小的服務之后&#xff0c;緊接著的一個問題就是&#xff0c;原本都在一個項目里&#xff0c;方法我可以隨便調用&#xff0c;但是拆開后&#xff0c;原來的方法就沒法直接調用了&#xff0c;這時候要怎么辦&#xff1f;Spring Cloud提供了feign&…

Asix下日志包沖突

為什么80%的碼農都做不了架構師&#xff1f;>>> Class org.apache.commons.logging.impl.SLF4JLogFactory does not implement org.apache.commons.logging. 最近集成asix包的時候發生如下錯誤&#xff0c;原因是程序運行時logFactoryImple加載了JBOSS下面的sff4j包…

kubernetes中mysql亂碼_在kubernetes中部署tomcat與mysql集群-Go語言中文社區

在kubernetes中部署tomcat與mysql集群之前必須要有以下這些基礎&#xff1a;1. 已安裝、配置kubernetes2. 集群中有tomcat與mysql容器鏡像3. 有docker基礎具體步驟部署tomcat創建tomcat RC對象我們想要在kubernetes集群中配置tomcat服務器&#xff0c;首先要保證集群中的節點上…

c# 測試運行時間毫秒級

long currentMillis (DateTime.Now.Ticks - (new DateTime(1970, 1, 1, 0, 0, 0, 0)).Ticks) / 10000;/*代碼*/long currentMillis1 (DateTime.Now.Ticks - (new DateTime(1970, 1, 1, 0, 0, 0, 0)).Ticks) / 10000;MessageBox.Show((currentMillis1 - currentMillis).ToStri…

nodejs_NodeJS歷險記

nodejsby Elliott McNary埃利奧特麥克納里(Elliott McNary) NodeJS歷險記 (Adventures in NodeJS) I built an app a couple of weeks ago after going through FreeCodeCamp’s Front-End curriculum and wanted to write an update as I head into NodeJS-land. I was final…

pytdx 獲取板塊指數_能否增加一個通過股票代碼,板塊指數代碼獲得中文名稱的接口?...

T0002/hq_cache/shex.tnfT0002/hq_cache/szex.tnf這個解碼就是。/***************************************************股票代碼列表和股票名稱T0002/hq_cache/shex.tnfT0002/hq_cache/szex.tnf***************************************************/struct TdxSymbolMap {cha…

靈動標簽調用友情鏈接

1、文字形式[e:loop{select * from [!db.pre!]enewslink where checked1 and classid1 order by myorder,20,24,0}] <li><a href"<?$bqr[lurl]?>" title"<?$bqr[lname]?>" target"_blank"><?$bqr[lname]?>&…

4-----Scrapy框架中選擇器的用法

Scrapy提取數據有自己的一套機制&#xff0c;被稱作選擇器&#xff08;selectors&#xff09;,通過特定的Xpath或者CSS表達式來選擇HTML文件的某個部分Xpath是專門在XML文件中選擇節點的語言&#xff0c;也可以用在HTML上。CSS是一門將HTML文檔樣式化語言&#xff0c;選擇器由它…

【原】Jenkins持續集成環境搭建之創建java項目的job【centos6.5 java maven git 項目】...

一、構建一個maven項目在jenkins主頁上&#xff0c;左側&#xff0c;選擇“新建”&#xff0c;然后填寫項目名稱&#xff0c;選擇“構建一個maven項目”二、Git配置保存之后&#xff0c;進入詳細配置頁面&#xff1a;這里的源碼管理&#xff1a;選擇git&#xff0c;輸入代碼的g…

linux修改java內存大小_Linux 和 windows修改java虛擬機內存大小

1、Java內存區域劃分&#xff1a; 運行時的數據區:方法區和堆(各個線程共享的內存區域)&#xff0c;程序計數器、Java虛擬機棧和本地方法棧(線程私有的) 程序計數器&#xff1a;當前線程所執行字節碼的行號指示器&#xff0c;字節碼解釋器就是通過改變計算器的值來選取下一條需…

html制作彩虹_制作彩虹

html制作彩虹by Gil Fewster吉爾弗斯特(Gil Fewster) 制作彩虹 (Making rainbows) This is a story about curiosity. It’s also about what happens when you stick a needle into your eye. If you happen to be eating a handful of grapes right this moment, maybe come…

python3 set_python3.x 基礎三:set集合

| clear(...) 清空一個集合| Remove all elements from this set.>>>set1.clear()>>>set1set()| copy(...) 影子復制&#xff0c;指向同一個內存地址| Return a shallow copy of a set. |>>> list1[3, 2, 1, 1, 2, 3, 4, 5]>>>…

Linux內核分析作業第八周

進程的切換和系統的一般執行過程 一、進程調度的時機 中斷處理過程&#xff08;包括時鐘中斷、I/O中斷、系統調用和異常&#xff09;中&#xff0c;直接調用schedule()&#xff0c;或者返回用戶態時根據need_resched標記調用schedule()&#xff1b; 內核線程可以直接調用sched…

iOS--數據存儲NSUserDefaults

2019獨角獸企業重金招聘Python工程師標準>>> 今天去面試&#xff0c;被問道NSUserDefaults的存取并手寫出來&#xff0c;一時想不起來&#xff0c;回來之后看看之前的筆記&#xff0c;稍作一些整理 NSUserDefaults是一個單例&#xff0c;在整個程序中只有一個實例對…

巨人肩膀_如何站在巨人的肩膀上

巨人肩膀“If I have seen further than others, it is by standing on the shoulders of giants.” — Isaac Newton“如果我能比其他人看到更多&#xff0c;那就是站在巨人的肩膀上。” —艾薩克牛頓 In 1676, Isaac Newton spoke of the great thinkers who came before him…

mysql 觸發器定義變量_MySQL 函數存儲過程觸發器定義簡單示例

1.變量提示NEW 是新值-- OLD 是舊值INSERT 只有NEW ----UPDATE有NEW和OLD ---DELETE只有OLD2.準備測試表(userinfo、userinfolog)use test;create table userinfo(userid int,username varchar(10),userbirthday date);create table userinfolog(logtime datetime,loginfo varc…

[EOJ439] 強制在線

Description 見EOJ439 Solution 先考慮不強制在線怎么做。 按詢問區間右端點排序&#xff0c;從左往右掃&#xff0c;維護所有后綴的答案。 如果掃到 \(a[i]\)&#xff0c;那么讓統計個數的 \(cnt[a[i]]\). 如果\(cnt[a[i]]<a[i]\)&#xff0c;那么在當前的右端點固定的情況…

大數據 就業 缺口_中國AI&大數據就業趨勢報告:平均月薪超2萬,缺口650萬人...

2019世界人工智能大會開幕式上&#xff0c;特斯拉公司聯合創始人兼首席執行官Elon Musk 和中國企業家俱樂部主席、聯合國數字合作高級別小組聯合主席馬云進行了一場“雙馬”對話。談到人工智能話題時&#xff0c;馬斯克認為&#xff0c;“未來的科技發展變化將超越我們的能力”…