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

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

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

 require_once __DIR__.'/../app/AppKernel.php';

 $kernel = new AppKernel('dev', true);
$kernel->loadClassCache();
//利用请求信息($_GET $_POST $_SERVER等等)构造Request对象
$request = Request::createFromGlobals();
//Symfony2框架核心工作就是把Request对象转换成Response对象
$response = $kernel->handle($request);
//向客户端输出Response对象
$response->send();
//完成一些耗时的后台操作,例如邮件发送,图片裁剪等等耗时工作
$kernel->terminate($request, $response);

    Symfony2框架通过客户端的请求信息来决定生成并返回响应的数据,我们下面的Symfony2源码分析重点就是AppKernel::handle方法。

    AppKernel::handle的实现继承于Kernel::handle

     /**
*
* @param Request $request Request对象实例
* @param int $type 请求的类型(子请求 or 主请求)
* @param bool $catch 是否捕捉异常
*
* @return Response Response对象实例
*
*/
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
//$this->booted Symfony2框架只启动一次
if (false === $this->booted) {
//初始化并启动所有注册在AppKernel里面的所有bundles(AppKernel::registerBundles)
//初始化container
//加载、缓存配置数据和路由数据、编译container容器等,为后面事件处理做准备。
$this->boot();
} //开启事件处理,Symfony2内核的请求处理过程本质是一系列的事件处理过程
return $this->getHttpKernel()->handle($request, $type, $catch);
}

    AppKernel::boot方法

     public function boot()
{
if (true === $this->booted) {
return;
} if ($this->loadClassCache) {
$this->doLoadClassCache($this->loadClassCache[], $this->loadClassCache[]);
} // init bundles
//初始化注册到AppKernel里的所有bundle(AppKernel::registerBundles)
$this->initializeBundles(); // init container
//初始化并编译缓存container,包括载入配置信息、编译信息、service等
//Symfony2的核心组件的加载,和各个组件之间的关联关系都在container容器初始化中完成,所以这会是下面详细描述
$this->initializeContainer(); //把bundle注入到container,并启动bundle
foreach ($this->getBundles() as $bundle) {
$bundle->setContainer($this->container);
$bundle->boot();
} //标记Symfony2只启动一次并启动成功
$this->booted = true;
}

    AppKernel::initializeContainer源码解析

     protected function initializeContainer()
{
//检查app/cache/dev[prod]缓存文件是否过期,以container缓存文件的最后修改时间为参考时间,
//如果app/cache/dev[prod]下的存在一个或者多个缓存文件的最后修改时间大于container缓存文件的
//最后修改时间,就判断为缓存过期。
//另外,如果$this->debug为false(即关闭debug的情况下)只要container缓存文件存在,那么就认为
//缓存不过期
$class = $this->getContainerClass();
$cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
$fresh = true;
if (!$cache->isFresh()) {
//初始化一个ContainerBuilder对象实例;
//自动加载所有注册的Bundle的DependencyInjection下的所有extension,Bundle可以通过extension来加载属于该Bundle配置(service的配置、
//路由的配置等等)、Bundle的全局变量等
//同时这些extension加载的信息都会被保存到container中;
//加载并保存compiler pass到container,为下一步compile做准备,我们可以通过compiler pass修改已经注册到container的service的属性
//compiler pass的官方文档http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html
$container = $this->buildContainer();
//执行compiler pass 的process方法,container的compile过程主要是执行上一步保存到container内的compiler pass 的process方法
$container->compile();
//生成container的缓存(appDevDebugProjectContainer.php),该container包含了service的获取方法、别名的映射关系
$this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); $fresh = false;
} require_once $cache; $this->container = new $class();
$this->container->set('kernel', $this); //...............
if (!$fresh && $this->container->has('cache_warmer')) {
$this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
}
}
     protected function prepareContainer(ContainerBuilder $container)
{
$extensions = array();
foreach ($this->bundles as $bundle) {
//加载DependencyInjection下的Extension,所有Extension必需实现Extension接口
if ($extension = $bundle->getContainerExtension()) {
$container->registerExtension($extension);
$extensions[] = $extension->getAlias();
} //开启debug的情况下,把bundles添加到recourses
if ($this->debug) {
$container->addObjectResource($bundle);
}
}
foreach ($this->bundles as $bundle) {
//通常用来添加compiler pass
$bundle->build($container);
} // ensure these extensions are implicitly loaded
$container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions));
}

    从AppKernel::initializeContainer可以看出Bundle和container是Symfony2框架的基础核心,container是Symfony2框架的所有组件的统一管理中心,Bundle就是一个功能模块的组织。

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

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

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

Symfony2源码分析——启动过程1的更多相关文章

  1. Symfony2源码分析——启动过程2

    文章地址:http://www.hcoding.com/?p=46 上一篇分析Symfony2框架源码,探究Symfony2如何完成一个请求的前半部分,前半部分可以理解为Symfony2框架为处理请求 ...

  2. quartz2.x源码分析——启动过程

    title: quartz2.x源码分析--启动过程 date: 2017-04-13 14:59:01 categories: quartz tags: [quartz, 源码分析] --- 先简单 ...

  3. mysql源码分析-启动过程

    mysql源码分析-启动过程 概要 # sql/mysqld.cc, 不包含psi的初始化过程 mysqld_main: // 加载my.cnf和my.cnf.d,还有命令行参数 if (load_d ...

  4. Spring Boot源码分析-启动过程

    Spring Boot作为目前最流行的Java开发框架,秉承"约定优于配置"原则,大大简化了Spring MVC繁琐的XML文件配置,基本实现零配置启动项目. 本文基于Spring ...

  5. Nginx学习笔记(六) 源码分析&启动过程

    Nginx的启动过程 主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程. 涉及到的基本函数 源码: /* * ...

  6. Zookeeper 源码分析-启动

    Zookeeper 源码分析-启动 博客分类: Zookeeper   本文主要介绍了zookeeper启动的过程 运行zkServer.sh start命令可以启动zookeeper.入口的main ...

  7. apiserver源码分析——启动流程

    前言 apiserver是k8s控制面的一个组件,在众多组件中唯一一个对接etcd,对外暴露http服务的形式为k8s中各种资源提供增删改查等服务.它是RESTful风格,每个资源的URI都会形如 / ...

  8. 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视GCC编译全过程 | 百篇博客分析OpenHarmony源码| v57.01

    百篇博客系列篇.本篇为: v57.xx 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视编译全过程 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...

  9. Tomcat源码分析——启动与停止服务

    前言 熟悉Tomcat的工程师们,肯定都知道Tomcat是如何启动与停止的.对于startup.sh.startup.bat.shutdown.sh.shutdown.bat等脚本或者批处理命令,大家 ...

随机推荐

  1. 【HDOJ】1063 Exponentiation

    这道题目莫名其妙的wa,又莫名其妙的过了. import java.util.Scanner; import java.math.BigDecimal; public class Main { pub ...

  2. SQL中游标的使用

    一般情况下,我们用SELECT这些查询语句时,都是针对的一行记录而言,如果要在查询分析器中对多行记录(即记录集)进行读取操作时,则需要使用到游标或WHILE等循环 游标的类型:  1.静态游标(不检测 ...

  3. 辗转相除法_欧几里得算法_java的实现(求最大公约数)

    辗转相除法,又被称为欧几里德(Euclidean)算法, 是求最大公约数的算法. 当然也可以求最小公倍数. 算法描述 两个数a,b的最大公约数记为GCD(a,b).a,b的最大公约数是两个数的公共素因 ...

  4. File System Minifilter Drivers(文件系统微型过滤驱动)入门

    问题: 公司之前有一套文件过滤驱动,但是在实施过程中经常出现问题,现在交由我维护.于是在边看代码的过程中,一边查看官方资料,进行整理. 这套文件过滤驱动的目的只要是根据应用层下发的策略来控制对某些特定 ...

  5. C++編程札記「基礎」

    一直以為自己最擅長的編程語言是C++,那時自己的水平停留在使用C++來實現數據結構中的各種ADT和ACM算法. 創建一個類,必須實現的成員函數 explicit構造函數 對於單參數構造函數,添加exp ...

  6. Java中可变长参数的方法

    原文转自:http://www.cnblogs.com/lanxuezaipiao/p/3190673.html 在Java5 中提供了变长参数(varargs),也就是在方法定义中可以使用个数不确定 ...

  7. Sublime代码折叠

    一.显示折叠小三角 1.点击Sublime的Preferences->Setting-Default菜单,打开它的配置文件. 2.找到行 // Fold buttons are the tria ...

  8. 多态 JAVA

    多态(Java)   一.多态 1.什么是多态? 不同的对象对于同一个操作,做出的响应不同 具有表现多种形态的能力的特征 2.使用多态的优点 : 为了实现统一调用 二.子类到父类的转换(向上转型) ① ...

  9. Python标准库:内置函数bytearray([source[, encoding[, errors]]])

    返回一个新字节数组.这个数组里的元素是可变的.而且每一个元素的值范围: 0 <= x < 256.能够通过"字节与字节数组操作"章节来查看相关字节数组的内容.以下说明一 ...

  10. Robotium API -- 判断测试结果的方法assert、is、search

    下面的这些方法都主要用来判断测试结果是否与预期结果相符,一般把is和search方法放在assert里面判断.assert最常用的还是assertThat方法,是Junit的判断,这里就不多说了. 断 ...