zoukankan      html  css  js  c++  java
  • Symfony2源码分析——启动过程1

        本文通过阅读分析Symfony2的源码,了解Symfony2启动过程中完成哪些工作,从阅读源码了解Symfony2框架。

        Symfony2的核心本质是把Request转换成Response的一个过程。

        我们大概看看入口文件(web_dev.php)的源码,入口文件从总体上描述了Symfony2框架的工作的流程:

     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::handle

     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就是一个功能模块的组织。

        如果你好奇service、配置参数是怎样被加载的,可以详细去了解Symfony2的Extension;如果你好奇怎么对已经加载了的service进一步完善和修改,可有详细了解Symfony2的compiler pass。

        到了这一步,Symfony2框架启动几乎完成,为后面的内核事件处理EventDispatcher::dispatch做好了准备。

        下一篇讲解Symfony2框架的内核事件处理。

  • 相关阅读:
    Android studio 搭建测试环境 创建虚拟机
    Halcon算子翻译——break
    Halcon算子翻译——throw
    halcon算子翻译——stop
    halcon算子翻译——return
    halcon算子翻译——par_join
    Halcon算子翻译——import
    Halcon算子翻译——global
    Halcon算子翻译——export_def
    Halcon算子翻译——exit
  • 原文地址:https://www.cnblogs.com/szuyuan/p/4028931.html
Copyright © 2011-2022 走看看