本文經過閱讀分析Symfony2的源碼,瞭解Symfony2啓動過程當中完成哪些工做,從閱讀源碼瞭解Symfony2框架。php
Symfony2的核心本質是把Request轉換成Response的一個過程。html
咱們大概看看入口文件(web_dev.php)的源碼,入口文件從整體上描述了Symfony2框架的工做的流程:web
1 require_once __DIR__.'/../app/AppKernel.php'; 2 3 $kernel = new AppKernel('dev', true); 4 $kernel->loadClassCache(); 5 //利用請求信息($_GET $_POST $_SERVER等等)構造Request對象 6 $request = Request::createFromGlobals(); 7 //Symfony2框架核心工做就是把Request對象轉換成Response對象 8 $response = $kernel->handle($request); 9 //向客戶端輸出Response對象 10 $response->send(); 11 //完成一些耗時的後臺操做,例如郵件發送,圖片裁剪等等耗時工做 12 $kernel->terminate($request, $response);
Symfony2框架經過客戶端的請求信息來決定生成並返回響應的數據,咱們下面的Symfony2源碼分析重點就是AppKernel::handle方法。緩存
AppKernel::handle的實現繼承於Kernel::handleapp
1 /** 2 * 3 * @param Request $request Request對象實例 4 * @param int $type 請求的類型(子請求 or 主請求) 5 * @param bool $catch 是否捕捉異常 6 * 7 * @return Response Response對象實例 8 * 9 */ 10 public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) 11 { 12 //$this->booted Symfony2框架只啓動一次 13 if (false === $this->booted) { 14 //初始化並啓動全部註冊在AppKernel裏面的全部bundles(AppKernel::registerBundles) 15 //初始化container 16 //加載、緩存配置數據和路由數據、編譯container容器等,爲後面事件處理作準備。 17 $this->boot(); 18 } 19 20 //開啓事件處理,Symfony2內核的請求處理過程本質是一系列的事件處理過程 21 return $this->getHttpKernel()->handle($request, $type, $catch); 22 }
AppKernel::boot方法框架
1 public function boot() 2 { 3 if (true === $this->booted) { 4 return; 5 } 6 7 if ($this->loadClassCache) { 8 $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]); 9 } 10 11 // init bundles 12 //初始化註冊到AppKernel裏的全部bundle(AppKernel::registerBundles) 13 $this->initializeBundles(); 14 15 // init container 16 //初始化並編譯緩存container,包括載入配置信息、編譯信息、service等 17 //Symfony2的核心組件的加載,和各個組件之間的關聯關係都在container容器初始化中完成,因此這會是下面詳細描述 18 $this->initializeContainer(); 19 20 //把bundle注入到container,並啓動bundle 21 foreach ($this->getBundles() as $bundle) { 22 $bundle->setContainer($this->container); 23 $bundle->boot(); 24 } 25 26 //標記Symfony2只啓動一次並啓動成功 27 $this->booted = true; 28 }
AppKernel::initializeContainer源碼解析源碼分析
1 protected function initializeContainer() 2 { 3 //檢查app/cache/dev[prod]緩存文件是否過時,以container緩存文件的最後修改時間爲參考時間, 4 //若是app/cache/dev[prod]下的存在一個或者多個緩存文件的最後修改時間大於container緩存文件的 5 //最後修改時間,就判斷爲緩存過時。 6 //另外,若是$this->debug爲false(即關閉debug的狀況下)只要container緩存文件存在,那麼就認爲 7 //緩存不過時 8 $class = $this->getContainerClass(); 9 $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug); 10 $fresh = true; 11 if (!$cache->isFresh()) { 12 //初始化一個ContainerBuilder對象實例; 13 //自動加載全部註冊的Bundle的DependencyInjection下的全部extension,Bundle能夠經過extension來加載屬於該Bundle配置(service的配置、 14 //路由的配置等等)、Bundle的全局變量等 15 //同時這些extension加載的信息都會被保存到container中; 16 //加載並保存compiler pass到container,爲下一步compile作準備,咱們能夠經過compiler pass修改已經註冊到container的service的屬性 17 //compiler pass的官方文檔http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html 18 $container = $this->buildContainer(); 19 //執行compiler pass 的process方法,container的compile過程主要是執行上一步保存到container內的compiler pass 的process方法 20 $container->compile(); 21 //生成container的緩存(appDevDebugProjectContainer.php),該container包含了service的獲取方法、別名的映射關係 22 $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); 23 24 $fresh = false; 25 } 26 27 28 require_once $cache; 29 30 $this->container = new $class(); 31 $this->container->set('kernel', $this); 32 33 //............... 34 if (!$fresh && $this->container->has('cache_warmer')) { 35 $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')); 36 } 37 }
1 protected function prepareContainer(ContainerBuilder $container) 2 { 3 $extensions = array(); 4 foreach ($this->bundles as $bundle) { 5 //加載DependencyInjection下的Extension,全部Extension必需實現Extension接口 6 if ($extension = $bundle->getContainerExtension()) { 7 $container->registerExtension($extension); 8 $extensions[] = $extension->getAlias(); 9 } 10 11 //開啓debug的狀況下,把bundles添加到recourses 12 if ($this->debug) { 13 $container->addObjectResource($bundle); 14 } 15 } 16 foreach ($this->bundles as $bundle) { 17 //一般用來添加compiler pass 18 $bundle->build($container); 19 } 20 21 // ensure these extensions are implicitly loaded 22 $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); 23 }
從AppKernel::initializeContainer能夠看出Bundle和container是Symfony2框架的基礎核心,container是Symfony2框架的全部組件的統一管理中心,Bundle就是一個功能模塊的組織。ui
若是你好奇service、配置參數是怎樣被加載的,能夠詳細去了解Symfony2的Extension;若是你好奇怎麼對已經加載了的service進一步完善和修改,可有詳細瞭解Symfony2的compiler pass。this
到了這一步,Symfony2框架啓動幾乎完成,爲後面的內核事件處理EventDispatcher::dispatch作好了準備。spa
下一篇講解Symfony2框架的內核事件處理。