Symfony2源码分析——启动过程2,symfony2源码
上一篇分析Symfony2框架源码,探究Symfony2如何完成一个请求的前半部分,前半部分可以理解为Symfony2框架为处理请求做准备工作,包括container生成、缓存、bundls初始化等一些列准备工作(Symfony2源码分析——启动过程1)。而这一篇讲的是Symfony2如何根据请求的数据生成Response对象,向客户端返回响应数据。
在分析前需要了解Symfony2的事件驱动机制:Symfony2事件驱动。
言归正传,Symfony2请求的工作流程其实是Symfony2内核的事件驱动完成的,下面是Symfony2框架定义好的内核事件:

我们可以编写事件监听器,监听相应的内核事件,在Symfony2触发该事件的时候,相应的事件监听器就会执行。监听和唤醒形象的描述,就像,你(事件监听器)参加校运会,去大会(Symfony2)登记(监听)参加50米短跑(事件),当50米短跑比赛开始了(事件被触发),那你就奔跑吧(监听器执行,其实就是一个执行函数,函数完成什么工作就取决于你的需求了),少年。
Symfony2的内核事件处理流程大部分工作都在HttpKernel::handleRaw方法中:
<span> 1</span> <span>private</span> function handleRaw(Request $request, $type =<span> self::MASTER_REQUEST) </span><span> 2</span> <span> { </span><span> 3</span> $<span>this</span>->requestStack-><span>push($request); </span><span> 4</span> <span> 5</span> <span>//</span><span> request </span><span> 6</span> <span>//</span><span> 初始化事件,事件对象会被传递给监听器,所以事件可以说是一个信息的载体,事件内存放着监听器感兴趣的数据。</span> <span> 7</span> $<span>event</span> = <span>new</span> GetResponseEvent($<span>this</span><span>, $request, $type); </span><span> 8</span> <span>//</span><span> 触发kernel.request事件,后续详细讲解EventDispatcher::dispatch方法的实现, </span><span> 9</span> <span>//</span><span> 这里我们需要知道的是,dispatcher把$event传递给所有监听了kernel.request事件的监听器,监听器将会执行。 </span><span>10</span> <span>//</span><span> kernel.request事件发生在controller执行之前,我们可以在这一步奏完成路由解析等为controller执行提供准备数据, </span><span>11</span> <span>//</span><span> 在这个过程允许我们直接生成Response对象,向客户端输出数据,那么controller就不会被执行了。</span> <span>12</span> $<span>this</span>->dispatcher->dispatch(KernelEvents::REQUEST, $<span>event</span><span>); </span><span>13</span> <span>14</span> <span>//</span><span> 如果我们在kernel.request事件生成了Response对象(响应数据),那么就跳过kernel.controller、kernel.view事件、 </span><span>15</span> <span>//</span><span> controller也会被跳过,直接执行kernel.response事件。</span> <span>16</span> <span>if</span> ($<span>event</span>-><span>hasResponse()) { </span><span>17</span> <span>return</span> $<span>this</span>->filterResponse($<span>event</span>-><span>getResponse(), $request, $type); </span><span>18</span> <span> } </span><span>19</span> <span>20</span> <span>//</span><span> load controller </span><span>21</span> <span>//</span><span> 根据路由规则返回 一个对象或者数组或者字符串 ,如果$controller是一个数组,$controller[0]是存放的是要执行的controller对象, </span><span>22</span> <span>//</span><span> $controller[0]存放的是controller对象执行的方法,即action,方法的参数没有保存在$controller数组中; </span><span>23</span> <span>//</span><span> 如果$controller是对象,那么该对象就实现了__invoke 方法; </span><span>24</span> <span>//</span><span> 如果$controller是字符串,那么$controller就是要运行的函数的函数名。 </span><span>25</span> <span>//</span><span> 图2是$controller的一个var_dump例子</span> <span>26</span> <span>if</span> (<span>false</span> === $controller = $<span>this</span>->resolver-><span>getController($request)) { </span><span>27</span> <span>throw</span> <span>new</span> NotFoundHttpException(sprintf(<span>'</span><span>Unable to find the controller for path "%s". Maybe you forgot to add the matching route in your routing configuration?</span><span>'</span>, $request-><span>getPathInfo())); </span><span>28</span> <span> } </span><span>29</span> <span>30</span> $<span>event</span> = <span>new</span> FilterControllerEvent($<span>this</span><span>, $controller, $request, $type); </span><span>31</span> <span>//</span><span> 触发kernel.controller事件,这个事件发生在controller执行前。我们可以通过监听这个事件在controller执行前修改controller, </span><span>32</span> <span>//</span><span> 或者完成一些动作。</span> <span>33</span> $<span>this</span>->dispatcher->dispatch(KernelEvents::CONTROLLER, $<span>event</span><span>); </span><span>34</span> $controller = $<span>event</span>-><span>getController(); </span><span>35</span> <span>36</span> <span>//</span><span> controller arguments </span><span>37</span> <span>//</span><span> 从request对象中获取controller方法的参数</span> <span>38</span> $arguments = $<span>this</span>->resolver-><span>getArguments($request, $controller); </span><span>39</span> <span>40</span> <span>//</span><span> call controller </span><span>41</span> <span>//</span><span> 执行controller</span> <span>42</span> $response =<span> call_user_func_array($controller, $arguments); </span><span>43</span> <span>44</span> <span>//</span><span> view </span><span>45</span> <span>//</span><span> 如果$response不是Response对象,那么kernel.view事件就会触发,监听kernel.view事件的监听器通过$response值生成Response对象。</span> <span>46</span> <span>if</span> (!<span>$response instanceof Response) { </span><span>47</span> $<span>event</span> = <span>new</span> GetResponseForControllerResultEvent($<span>this</span><span>, $request, $type, $response); </span><span>48</span> $<span>this</span>->dispatcher->dispatch(KernelEvents::VIEW, $<span>event</span><span>); </span><span>49</span> <span>50</span> <span>if</span> ($<span>event</span>-><span>hasResponse()) { </span><span>51</span> $response = $<span>event</span>-><span>getResponse(); </span><span>52</span> <span> } </span><span>53</span> <span>54</span> <span>if</span> (!<span>$response instanceof Response) { </span><span>55</span> $msg = sprintf(<span>'</span><span>The controller must return a response (%s given).</span><span>'</span>, $<span>this</span>-><span>varToString($response)); </span><span>56</span> <span>57</span> <span>//</span><span> the user may have forgotten to return something</span> <span>58</span> <span>if</span> (<span>null</span> ===<span> $response) { </span><span>59</span> $msg .= <span>'</span><span> Did you forget to add a return statement somewhere in your controller?</span><span>'</span><span>; </span><span>60</span> <span> } </span><span>61</span> <span>throw</span> <span>new</span><span> \LogicException($msg); </span><span>62</span> <span> } </span><span>63</span> <span> } </span><span>64</span> <span>65</span> <span>//</span><span> 触发kernel.response事件,在向客户端输出Response对象前,我们可以对Response对象进行修改, </span><span>66</span> <span>//</span><span> 例如修改response头部,设置缓存、压缩输出数据等。 </span><span>67</span> <span>68</span> <span>//</span><span> 接着触发kernel.finish_request事件,把当前请求从请求栈中弹出,当前请求就完成。</span> <span>69</span> <span>return</span> $<span>this</span>-><span>filterResponse($response, $request, $type); </span><span>70</span> <span>71</span> <span>//</span><span> 千万别忘记了,filterResponse执行完后,Symfony2内核事件处理流程还有最后一步,位于app_dev.php[app.php]最后一行, </span><span>72</span> <span>//</span><span> $kernel->terminate($request, $response);这个方法触发kernel.terminate事件,此时,Symfony2已经响应了客户端的请求, </span><span>73</span> <span>//</span><span> 向客户端输出了Response对象。监听kernel.terminate事件的监听器,主要是为了完成一些耗时的操作,操作的结果不需要返回给 </span><span>74</span> <span>//</span><span> 客户端的,例如邮件发送、图片压缩等等。 </span><span>75</span> <span>//</span><span> 到这里,Symfony2的整个流程就走完了。</span> <span>76</span> }
<span>HttpKernel::filterResponse方法和</span>HttpKernel::finishRequest方法:


图2
Symfony2框架的事件分发机制的核心代码:
<span> 1</span> <span>public</span> function dispatch($eventName, Event $<span>event</span> = <span>null</span><span>) </span><span> 2</span> <span> { </span><span> 3</span> <span>if</span> (<span>null</span> === $<span>event</span><span>) { </span><span> 4</span> $<span>event</span> = <span>new</span><span> Event(); </span><span> 5</span> <span> } </span><span> 6</span> <span> 7</span> $<span>event</span>->setDispatcher($<span>this</span><span>); </span><span> 8</span> $<span>event</span>-><span>setName($eventName); </span><span> 9</span> <span>10</span> <span>if</span> (!isset($<span>this</span>-><span>listeners[$eventName])) { </span><span>11</span> <span>return</span> $<span>event</span><span>; </span><span>12</span> <span> } </span><span>13</span> <span>14</span> <span>//</span><span> $eventName即:KernelEvents::REQUEST、KernelEvents::CONTROLLER、KernelEvents::VIEW、KernelEvents::RESPONSE、KernelEvents::TERMINATE等 </span><span>15</span> <span>//</span><span> getListeners返回所有监听$eventName事件的监听器</span> <span>16</span> $<span>this</span>->doDispatch($<span>this</span>->getListeners($eventName), $eventName, $<span>event</span><span>); </span><span>17</span> <span>18</span> <span>return</span> $<span>event</span><span>; </span><span>19</span> <span> } </span><span>20</span> <span>21</span> <span>protected</span> function doDispatch($listeners, $eventName, Event $<span>event</span><span>) </span><span>22</span> <span> { </span><span>23</span> <span>//</span><span> 监听器执行</span> <span>24</span> <span>foreach</span> ($listeners <span>as</span><span> $listener) { </span><span>25</span> call_user_func($listener, $<span>event</span>, $eventName, $<span>this</span><span>); </span><span>26</span> <span>//</span><span> 如果其中一个监听器把$event的propagationStopped属性设置为true,那么表示$eventName这一事件终止执行, </span><span>27</span> <span>//</span><span> 事件不会往$listeners里尚未执行的监听器传递该事件。</span> <span>28</span> <span>if</span> ($<span>event</span>-><span>isPropagationStopped()) { </span><span>29</span> <span>break</span><span>; </span><span>30</span> <span> } </span><span>31</span> <span> } </span><span>32</span> }
我个人感觉毛德操先生的书linux内核情景分析,分析的很透彻的,对整个Linux内核的讲解很不错.具体到启动过程,这个启动过程很泛的,你只需要知道整体的启动过程,其他的细节,还得看内核源码讲解,所以,推荐你看点博客了解下启动大体过程,具体到每个细节,看linux内核情景分析吧.
1.这个dialog是由PhoneWindowManager控制的,在PhoneWindowManager的interceptKeyTq方法中,代码是这一行
mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
mProwerLongPress是一个Runnable,执行时调用GlobalActions中的showDialog方法。所以这个dialog是由GlobalActions管理的,PowerDialog是之前版本中的,现在已经弃用了。
2.可以在GlobalActions中createDialog方法中mSilentModeToggle action的onToggle方法中加入
mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, on ? AudioManager.VIBRATE_SETTING_ON : AudioManager.VIBRATE_SETTING_OFF);
这一句,仿照铃声的处理,应该没问题,不过没试所以也不能确定。
希望对你有帮助。

Linux内核作为操作系统的核心部分,承担着管理硬件资源、提供系统调用等重要功能。本文将深入探讨Linux内核的五大部分,包括进程管理、文件系统、网络通信、设备驱动和内存管理,并提供详细的介绍和代码示例。一、进程管理进程的创建在Linux内核中,进程的创建通过fork()系统调用来实现。下面是一个简单的示例代码:#include

尊敬的读者们,您好!在此,我有幸与您分享我作为资深网络工程师,以其专业的技术在Linux内核TCP协议栈的研发及优化工作中所积累下的宝贵经验与技巧。相信通过此文,我们能互相学习、探讨,为对该领域有着浓厚兴趣或正在进行相关工作的你们带来实际且有益的参考资料。1.TCP连接建立TCP连接建立乃是TCP协议栈关键事务,然而面临诸多连接问题并不少见。经过深思熟虑及详细调试,我挖掘出一些普遍存在且实用的问题及其解决方案,包括防范SYN洪泛攻击(可透过调整系统参数)及应对网络拥塞(亦即运用TCPFastOp

篇幅长,技术内容多,点击关注不走散。序言:了解Linux内核一个计算机系统是一个硬件和软件的共生体,它们相互依赖,不可分割。计算机的硬件linux内核移植步骤,富含外围设备、处理器、内存、硬盘和其他的电子设备组成计算机的缸体。并且没有软件来操作和控制它,自身是不能工作的。完成这个控制工作的软件就称为操作系统,在Linux的术语中被称为“内核”,也可以称为“核心”。Linux内核的主要模块(或组件)分以下几个部份:储存管理、CPU和进程管理、文件系统、设备管理和驱动、网络通讯linux论坛,以及系

上篇分析了RISC-V Linux启动的页表创建,提到RISC-V Linux入口地址必须2M对齐,今天讲讲如何解决2M对齐的问题,或者说如何优化部分内存。

这是一个深度探索Linux内核源代码分布的关于1500字的文章。因为篇幅有限,我们将重点介绍Linux内核源代码的组织结构,并提供一些具体的代码示例,以帮助读者更好地理解。Linux内核是一个开源的操作系统内核,其源代码托管在GitHub上。整个Linux内核源代码分布非常庞大,包含了几十万行代码,涉及到多个不同的子系统和模块。要深入了解Linux内核源代码

论述了Linux内核在计算机操作系统中发挥重要作用的观点linux内核设计和实现,通过深入解析Linux内核设计及实际应用,揭示了它在该领域的显著地位和影响力量。1.优化的内存管理通过采用虚拟内存管理技术,Linux内核能高效率地完成内存分配与回收。在置换页面算法帮助下linux内核设计和实现,精确处理物理内存至虚拟内存之间的映射关系。依据应用程序具体需求,实现可动调整,从而提升了整个系统性能表现。2.强大的进程管理内核借助其卓越的多任务处理技术,使多个进程能够和谐共处于单一系统中。精心制定的进

安卓系统与Linux内核是息息相关的两个实体,它们之间的关系紧密而又复杂。在安卓系统中,Linux内核充当着重要的角色,为安卓系统提供了底层的硬件驱动和系统调用支持。本文将探讨安卓系统与Linux内核之间的关系,以及它们是如何交互、协同工作的,同时提供一些具体的代码示例。安卓系统是基于Linux内核开发的移动操作系统,主要用于智能手机、平板电脑等移动设备。L

Linux内核是操作系统的核心,它控制对系统资源(例如:CPU、I/O设备、物理内存和文件系统)的访问。在引导过程中以及系统运行时,内核会将各种消息写入内核环形缓冲区。这些消息包括有关系统操作的各种信息。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3 Linux新版
SublimeText3 Linux最新版

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),