简而言之我们知道laravel/symfony框架是由一堆组件粘合在一起的。会有一个eventcomponent组件,比较特别。它就像一个中介,是框架层的全局组件,负责不同组件之间的通信和数据传输。说是全局的,就是说在整个请求生命周期中,事件对象是单例的,对象不能创建新的实例。每次从容器中获取到标记为'event'的事件对象,它仍然是原来的事件对象。为什么?想要这样做吗?这很简单。如果不是单例,则在第一个事件组件中注册10个event事件。在某个组件中,你想在事件对象中触发一个邮件事件'mail',但是如果此时从容器中发送,如果获取到的事件组件不是原来的事件组件,那么对应的handler找不到邮件事件。可以看到laravel的EventServiceProvider在容器中注册'event'对象时使用了singleton()单例注册,这样事件对象就永远是那个。据说是负责跨组件通信的,也就是说对于数据库下的一个模型对象比如account模型,在处理保存一个account模型到数据库的逻辑的时候,如果需要多加几个逻辑,比如发送邮件,数据进入Validation之前需要验证数据库,需要为这个账号写一个log日志。这些逻辑需要通过MailComponent/ValidationComponent/LogComponent中的对象来处理。$account->save()之后是不是要写一大堆逻辑?那代码会不会一团糟。更何况,我还想在保存前和保存后做一些逻辑,这还不算完。有没有这样一种实用的方法,可以让我省去前一两行代码和最后一两行代码,把这些逻辑解耦成小逻辑,这样代码会更干净。(1)为什么需要事件系统?在代码层面,为了代码解耦,将一个地方的一大块逻辑解耦成多个细分的代码;出于性能的考虑,事件队列功能模拟了异步处理,将耗时的任务放到队列中,让队列慢慢的把这些任务一个一个的过一遍。(2)事件架构是如何构建的?事件架构实际上非常简单。它是框架层的一个全局组件:事件组件。从上面的描述,我们知道它应该有几个功能:事件注册功能,事件触发功能,加上一个高级功能,将事件异步放入队列中处理,比如事件注册功能\\Illuminate\\Events\\Dispatcherlaravel中的::listen(),事件触发函数\\Illuminate\\Events\\Dispatcher::dispatch()。事件系统就是这么简单。(3)一个event事件可以有多个handler/listener,一个handler/listener可以监听多个事件。事件组件应该如何支持这个?要求多个处理程序/侦听器(一个可调用对象或一个类名)来侦听一个事件'event'非常简单,然后多次注册\\Illuminate\\Events\\Dispatcher::listen($event_name,$handler),$event_name是一样的,但是$handler是不同的。$handler会按照注册的先后顺序执行。当然symfony支持在第三个参数priority中设置$handler的执行顺序。要求处理程序/侦听器侦听多个事件非常简单。把handler做成一个类,然后在里面做一个$events数组属性,用来设置监听哪些事件。Laravel/symfony将这个处理程序称为事件订阅者,仅此而已。不想画图详细解释。按照上面几句话,从架构层面看laravelevent/symfonyevent的事件系统文章就很简单了。建议仔细阅读官网这两篇文章。其他细节用于上述设计目的。说了这么多,一句话可以概括:事件系统在框架层就像一个全局的数据库,具有事件的存储、注册和触发,代码解耦,实现跨组件通信等功能。.
