主要內容
Startable Facility原理分析
……
在Castle IOC容器實踐之Startable Facility(一)中我們已經看到了如何去使用Startable Facility,本文將對它的原理做一些分析。先看一下接口IStartable,它的實現代碼如下:
public interface IStartable
{
void Start();
void Stop();
}
代碼是相當的簡單,只有兩個方法,分別在組件創建的時候和銷毀的時候執行,這就涉及到了組件的生命周期管理。在Windsor中,接口ILifecycleConcern提供特定的組件生命周期管理:
public interface ILifecycleConcern
{
void Apply( ComponentModel model, object component );
}
現在我們要實現組件的自動創建和銷毀,就需要實現接口ILifecycleConcern,在Startable Facility中分別用兩個類來實現,第一個類StartConcern,它判斷如果組件實現了接口IStartable,則直接調用它的Start()方法;如果組件是用特性startMethod,則獲取並調用具有startMethod特性的方法:
public class StartConcern : ILifecycleConcern
{
private static readonly StartConcern _instance = new StartConcern();
protected StartConcern()
{
}
public static StartConcern Instance
{
get { return _instance; }
}
public void Apply(ComponentModel model, object component)
{
if (component is IStartable)
{
(component as IStartable).Start();
}
else if (model.Configuration != null)
{
String startMethod = model.Configuration.Attributes["startMethod"];
if (startMethod != null)
{
MethodInfo method = model.Implementation.GetMethod(startMethod);
method.Invoke(component, null);
}
}
}
}
第二個類是StopConcern,它判斷如果組件實現了接口IStartable,則直接調用它的Stop()方法;如果組件是用特性stopMethod,則獲取並調用具有stopMethod特性的方法:
public class StopConcern : ILifecycleConcern
{
private static readonly StopConcern _instance = new StopConcern();
protected StopConcern()
{
}
public static StopConcern Instance
{
get { return _instance; }
}
public void Apply(ComponentModel model, object component)
{
if(component is IStartable)
{
(component as IStartable).Stop();
}
else if (model.Configuration != null)
{
String stopMethod = model.Configuration.Attributes["stopMethod"];
if (stopMethod != null)
{
MethodInfo method = model.Implementation.GetMethod(stopMethod);
method.Invoke(component, null);
}
}
}
}
好了,知道了Startable Facility如何管理組件的生命周期,我們就來看看真正的Startable Facility是如何實現的。每一個Facility都是滿足這樣的一個繼承關系:
圖1 Facility繼承關系圖
其中的Abstract Facility提供了一些默認的實現,Facility可以直接實現IFacility,也可以繼承於Abstract Facility。IFacility的實現如下:
public interface IFacility
{
void Init(IKernel kernel, IConfiguration facilityConfig);
void Terminate();
}
那麼到底如何讓組件滿足依賴性後就自動執行呢?注意到再Startable Facility的Init()注冊了這樣的兩個事件:
protected override void Init()
{
converter = (ITypeConverter) Kernel.GetSubSystem(SubSystemConstants.ConversionManagerKey);
Kernel.ComponentModelCreated +=
new ComponentModelDelegate(OnComponentModelCreated);
Kernel.ComponentRegistered +=
new ComponentDataDelegate(OnComponentRegistered);
}
分別為OnComponentModelCreated和OnComponentRegistered。當我們注冊一個組件時首先會出發OnComponentRegistered事件,在它裡面判斷組件是否滿足依賴性,如果不滿足,則添加到一個等待列表中,否則就直接啟動,然後再對這個等待列表進行檢測,看添加改組件後,列表中是否有組件滿足了依賴性:
private void OnComponentRegistered(String key, IHandler handler)
{
bool startable = (bool) handler.ComponentModel.ExtendedProperties["startable"];
if (startable)
{
if (handler.CurrentState == HandlerState.WaitingDependency)
{
waitList.Add( handler );
}
else
{
Start( key );
}
}
CheckWaitingList();
}
private void CheckWaitingList()
{
IHandler[] handlers = (IHandler[]) waitList.ToArray( typeof(IHandler) );
IList validList = new ArrayList();
foreach(IHandler handler in handlers)
{
if (handler.CurrentState == HandlerState.Valid)
{
validList.Add(handler);
waitList.Remove(handler);
}
}
foreach(IHandler handler in validList)
{
Start( handler.ComponentModel.Name );
}
}
剛才說到,如果滿足了依賴性,則會請求創建這個組件:
private void Start(String key)
{
object instance = Kernel[key];
}
這時就觸發了OnComponentModelCreated事件,這時就該用到開始我們所講的那兩生命周期處理的類了:
private void OnComponentModelCreated(ComponentModel model)
{
bool startable =
CheckIfComponentImplementsIStartable(model) || HasStartableAttributeSet(model);
model.ExtendedProperties["startable"] = startable;
if (startable)
{
model.LifecycleSteps.Add(
LifecycleStepType.Commission, StartConcern.Instance );
model.LifecycleSteps.Add(
LifecycleStepType.Decommission, StopConcern.Instance );
}
}
首先還是先判斷組件是否實現了IStartable接口或這時候有特性startable,如果沒有那也就不用自動啟動了,否則就把StartConcern和StopConcern分別注冊為組件的生命周期開始行為和生命周期結束行為,(關於組件的生命周期的詳細內容可以參考我前面寫的Castle IOC容器組件生命周期管理)。此時組件進入生命周期開始,會調用StartConcern的Apply()方法,這時就觸發組件的Start()方法,同樣在組件銷毀時調用StopConcern的Apply()方法,這時就會調用組件的Stop()方法。這樣就完成整個了組件的自動執行與銷毀的全過程。