本来应该继续介绍各个组件的启动流程,这里先补充下mule所使用的一些设计模式,方便从宏观上对mule的代码结构进行理解。
首先介绍的是状态机模式,该模式在mule中的使用随处可见。具体状态机管理的实现如下:
严格遵循SEDA规范,一个状态就是一个阶段,每个phase只关心当前是否可以进入该状态,接着统一调用invokePhase,在该函数中进行状态的设置以及回调函数的调用。这里使用哪个回调函数由外部传入,采用了Command模式。
针对状态之间的变迁,都需要对应的manager进行管理。针对mule context以及registry(transient registry,registry broker)有对应的lifecycle进行生命周期的管理。这三个lifecycle manager 都在mule context创建时被实例化,而spring registry的lifecycle manager在start时被实例化。
mule context没有注册单独注册其状态,而是使用默认的状态机,但是注册了状态变迁表。此时invoke的对象,在lifecycle Manager初始化是就由外部传入。
此外还会为model,connector,flow,component等实例创建对应的lifecycle manager,并触发对应实例的init函数,在init函数中设置对应的消息处理函数链,消息监听函数,并将消息注入到mule context中。针对每一个seda stage实例,都会为之创建一个事件队列。
在调用start之后,所有对象的也会通过生命周期管理触发其start函数的调用,从而完成实例的启动。
每一个含有生命周期的对象,都有对应的状态机管理器,对象需要注入其拥有的状态,以及各个状态间的转移关系,还有状态发生转移时需要进行的操作,此处操作的输入采用了command模式。
当状态发生转移时,就会触发相应的事件通知。同时进入回调之前,先记录将要进入的状态,在回调结束后,更新当前状态 。
状态转移方式:
1)直接转移:如果前后状态是可以直接转移的,那么直接调用对应的回调函数,并设置相关状态
2)间接转移:如果前后状态不可以直接转移的,那么需要调用中间状态的回调函数,并设置相关状态,最终转移到目标状态。
具体实现
通过RegistryLifecycleManager统一入口invokePhase,进行各个模块的状态触发。状态以及对应的回调,在模块初始化阶段完成。
需要初始化的模块在mule context状态转移为start时注册。目前需要启动的对象有transactionQueueManager,connector,agent,model,flowConstruct,startable等(这里是按顺序启动!针对上述对象的所有实例都需要进行初始化操作,通过类型来查找,默认情况下针对一个对象只能有一个实例,这些实例在spring的refresh过程中创建为bean实例)。不在此阶段初始化的对象有registry, mulecontext, messageSource, component, outboundRouterCollection,outboundRouter。
如果是通过web启动的,则在加载配置完成后,如果muleContext已经start则主动触发所有实例,否则触发一次muleContext的start状态转移,通过对象类型来查找对应实例进行start,这里如果是spring则调用application context来查找对应的bean。
这里使用的反射机制查找并自动执行对应实例的start方法!--invoke具体执行的方法通过getMethod方法来确定。这里由于只有一个start方法,因此通过getMethod方法获取的方法列表的首个方法就是start。如果有多个方法的话,start必须放在最前面了。
以muleContext为例,其注册的状态机如下:
其init阶段的触发是doCreateMuleContext时,手动调用执行的。
其start阶段的执行是在mulecontext初始化,配置加载完毕后,如果是独立部署则由外部主动调用start函数触发的。如果是潜入到web容器中部署,则加载配置完成后,主动调用applyLifecycle触发创建对象的start状态。
状态机模式与观察者模式紧密关联,因此下一节重点介绍观察者模式在mule中的使用。