Symfony2源码分析——启动过程2,symfony2源码_PHP教程
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);
这一句,仿照铃声的处理,应该没问题,不过没试所以也不能确定。
希望对你有帮助。

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas











Sebagai bahagian teras sistem pengendalian, kernel Linux bertanggungjawab untuk fungsi penting seperti mengurus sumber perkakasan dan menyediakan panggilan sistem. Artikel ini akan menyelidiki lima bahagian utama kernel Linux, termasuk pengurusan proses, sistem fail, komunikasi rangkaian, pemacu peranti dan pengurusan memori, dan menyediakan pengenalan terperinci dan contoh kod. 1. Penciptaan Proses Pengurusan Proses Dalam kernel Linux, penciptaan proses dilaksanakan melalui panggilan sistem fork(). Berikut ialah kod contoh mudah: #include

Ini ialah artikel 1500 perkataan yang meneroka pengedaran kod sumber kernel Linux secara mendalam. Oleh kerana ruang yang terhad, kami akan menumpukan pada struktur organisasi kod sumber kernel Linux dan menyediakan beberapa contoh kod khusus untuk membantu pembaca memahami dengan lebih baik. Kernel Linux ialah kernel sistem pengendalian sumber terbuka yang kod sumbernya dihoskan pada GitHub. Keseluruhan pengedaran kod sumber kernel Linux adalah sangat besar, mengandungi ratusan ribu baris kod, melibatkan berbilang subsistem dan modul yang berbeza. Untuk mendapatkan pemahaman yang lebih mendalam tentang kod sumber kernel Linux

Artikel sebelumnya menganalisis penciptaan jadual halaman untuk permulaan RISC-V Linux Telah disebutkan bahawa alamat kemasukan RISC-V Linux mesti sejajar 2M Hari ini saya akan bercakap tentang cara menyelesaikan masalah penjajaran 2M, atau cara mengoptimumkan sebahagian daripada ingatan itu.

Ia panjang dan mempunyai banyak kandungan teknikal, jadi klik untuk mengikutinya dan anda tidak akan tersesat. Prakata: Memahami Kernel Linux Sistem komputer ialah simbiosis perkakasan dan perisian ia saling bergantung dan tidak boleh dipisahkan. Perkakasan komputer Langkah pemindahan kernel Linux termasuk peranti persisian, pemproses, memori, pemacu keras dan peranti elektronik lain yang membentuk silinder komputer. Dan tanpa perisian untuk mengendalikan dan mengawalnya, ia tidak boleh berfungsi dengan sendirinya. Perisian yang melengkapkan kerja kawalan ini dipanggil sistem pengendalian Dalam terminologi Linux, ia dipanggil "kernel" atau "teras". Modul utama (atau komponen) kernel Linux dibahagikan kepada bahagian berikut: pengurusan storan, pengurusan CPU dan proses, sistem fail, pengurusan peranti dan pemacu, komunikasi rangkaian forum Linux dan sistem

Hello pembaca yang dikasihi! Di sini, saya berbesar hati untuk berkongsi dengan anda pengalaman dan kemahiran berharga yang telah saya kumpulkan sebagai jurutera rangkaian kanan dengan kemahiran profesional saya dalam pembangunan dan pengoptimuman tindanan protokol TCP kernel Linux. Saya percaya bahawa melalui artikel ini, kita boleh belajar daripada satu sama lain dan membincangkannya, dan membawa bahan rujukan yang praktikal dan berguna kepada anda yang mempunyai minat yang kuat dalam bidang ini atau sedang mengusahakannya. 1. Penubuhan sambungan TCP Penubuhan sambungan TCP ialah urus niaga utama timbunan protokol TCP, tetapi bukan perkara biasa untuk menghadapi banyak masalah sambungan. Selepas pertimbangan yang teliti dan penyahpepijatan terperinci, saya menemui beberapa masalah biasa dan praktikal serta penyelesaiannya, termasuk mencegah serangan banjir SYN (dengan melaraskan parameter sistem) dan menangani kesesakan rangkaian (iaitu, menggunakan TCPFastOp

Membincangkan pandangan bahawa kernel Linux memainkan peranan penting dalam reka bentuk dan pelaksanaan kernel Linux melalui analisis mendalam tentang reka bentuk kernel Linux dan aplikasi praktikal, ia mendedahkan kedudukan dan pengaruhnya yang menonjol dalam bidang ini. 1. Pengurusan memori yang dioptimumkan Dengan menggunakan teknologi pengurusan memori maya, kernel Linux boleh melengkapkan peruntukan memori dan kitar semula dengan cekap. Dengan bantuan algoritma halaman gantian, kernel Linux direka bentuk dan dilaksanakan untuk mengendalikan hubungan pemetaan antara memori fizikal dan memori maya dengan tepat. Pelarasan fleksibel boleh dibuat berdasarkan keperluan khusus aplikasi, dengan itu meningkatkan prestasi sistem keseluruhan. 2. Kernel pengurusan proses yang berkuasa menggunakan teknologi pelbagai tugas yang sangat baik untuk membolehkan pelbagai proses wujud bersama secara harmoni dalam satu sistem. Dirumus dengan teliti

Sistem Android dan kernel Linux adalah dua entiti yang berkait rapat, dan hubungan antara mereka adalah rapat dan kompleks. Dalam sistem Android, kernel Linux memainkan peranan penting, menyediakan pemacu perkakasan asas dan sokongan panggilan sistem untuk sistem Android. Artikel ini akan meneroka hubungan antara sistem Android dan kernel Linux, cara ia berinteraksi dan berfungsi bersama, serta menyediakan beberapa contoh kod khusus. Android ialah sistem pengendalian mudah alih yang dibangunkan berdasarkan kernel Linux dan digunakan terutamanya untuk peranti mudah alih seperti telefon pintar dan tablet. L

Kernel Linux ialah teras sistem pengendalian dan mengawal akses kepada sumber sistem seperti CPU, peranti I/O, memori fizikal dan sistem fail. Semasa proses but dan semasa sistem berjalan, kernel menulis pelbagai mesej ke penimbal cincin kernel. Mesej ini termasuk pelbagai maklumat tentang operasi sistem.
