1. 程式人生 > 實用技巧 >ABP模組系統

ABP模組系統

模組系統簡介

ABP 為建立模組及組織它們提供基礎框架。一個模組可依賴於另一個模組。通常地,一個程式集做為一個模組。如果你的應用是多個程式集,建議為每個程式集定義一個模組。

模組的本質就是可重用性,你可以在任意的地方去呼叫,而且通過實現模組,你寫的模組也可以給別人用。

模組定義

一個模組定義成一個繼承於 AppModule 類的類。 假設我們正在開發一個能用於不同應用的 Blog 模組,最簡單的模組定義可能像如下所示:

public class MyBlogApplicationModule : AbpModule
{
  public override void Initialize()
  {
        IocManager.RegisterAssemblyByConvention(
Assembly.GetExecutingAssembly());
  }
}

模組定義類負責把自己的類註冊到依賴注入裡(約定做法如上所示)、配置應用和其它模組、為應用新增新的特性等...

生命週期方法

ABP 在應用啟動和關閉時,為模組呼叫一些特定的方法。你可以重寫這些方法來執行一些特定的任務。

ABP 按依賴關係順序呼叫這些方法。如果模組 A 依賴於模組 B,模組 B 會在模組 A 前初始化,確切的啟動方法順序是:預初始化 B,預初始化 A,初始化 B,提交 B 和提交 A。這就是依賴路線。Shutdown 方法類似,不過順序是相反的。

PreInitialize(預初始化)

應用啟動時最先呼叫這個方法,它通常在初始化前將模組內的配置資訊新增到框架或是處理其它模組所需執行的操作。

也可以在這裡寫一些特定的程式碼執行在依賴注入註冊之前。例如,你想建立一個約定註冊(Conventional Registration)類,你應該在這裡使用 IocManager.AddConventionalRegisterer 方法來註冊這個類。

Initialize(初始化)

依賴注入註冊一般都在這裡完成,一般都使用 IocManager.RegisterAssemblyByConvention 方法。如果想自定義依賴註冊,可以依照 ABP 提供的其他方式完成註冊(手動註冊),如使用 IocManager.Register 方法直接註冊或是Castle Windsor 註冊.

PostInitialize(提交初始化)

在啟動過程中最後呼叫這個方法,此時可以安全的解析依賴。

Shutdown(關閉)

當應用關閉時呼叫這個方法。

模組依賴

一個模組可以依賴於其它模組,它要求使用DenpendsOn特性顯式地宣告依賴關係,如下:

[DependsOn(typeof(MyBlogCoreModule))]
public class MyBlogApplicationModule : AbpModule
{
  public override void Initialize()
  {
    IocManager.RegisterAssemblyByConvention(
Assembly.GetExecutingAssembly());
  }
}

由於我們宣告 MyBlogApplicationModule 依賴於 MyBlogCoreModule,所以 MyBlogCoreModule 會在 MyBlogApplicationModule 前初始化。
ABP 可以從 startup 模組解析依賴並按順序初始化它們。startup 模組作為層次最淺的,最後初始化模組

呼叫鏈路

如存在三個模組,模組 A 作為系統的啟動模組,依賴著模組 B,而模組 B 依賴著模組 C,則在啟動時,會依照這個依賴關係,從最深層模組開始解析,如同解析依賴注入一般。


可對模組系統提供的三個生命週期方法斷點跟蹤,可以得到如下的呼叫順序。從深層次模組開始到淺層模組,先呼叫 PreInitialize,全部呼叫完畢再回到深層次模組呼叫 Initialize,最後再次回到深層次呼叫 PostInitialize,全部執行完畢,模組載入的工作完成。

該部分呼叫關係也可以直接翻閱原始碼

publicvirtualvoidStartModules()
{
varsortedModules = _modules.GetSortedModuleListByDependency();
sortedModules.ForEach(module => module.Instance.PreInitialize());
sortedModules.ForEach(module => module.Instance.Initialize());
sortedModules.ForEach(module => module.Instance.PostInitialize());
}

外掛模組

雖然從啟動模組開始通過依賴項載入模組,但ABP也可以動態載入模組,AbpBootstrapper類定義了PlugInSources屬性,該屬性可用於新增資源以動態載入外掛模組。

外掛源可以是實現IPlugInSource介面的任何類,PlugInFolderSource類實現從資料夾中的程式集獲取外掛模組。

在 Abp.AspNetCoreNuget 包中,提供了AddAbp 擴充套件方法,可用於實現在 Startup 類中新增外掛源。

services.AddAbp<MyStartupModule>(options =>
{
    options.PlugInSources.Add(new FolderPlugInSource(@"C:\MyPlugIns"));
});

也可以呼叫 AddFolder擴充套件方法來從資料夾中的程式集中獲取模組。

services.AddAbp<MyStartupModule>(options =>
{
    options.PlugInSources.AddFolder(@"C:\MyPlugIns");
});

附加程式集

IAssemblyFinder和ITypeFinder的預設實現,這兩個介面在ABP中用於去識別特定類,僅在給定的程式集中查詢模組所處的程式集和型別。可以通過重寫模組中的GetAdditionalAssemblies方法去包含其他程式集,如獲取非模組的程式集,將其加入到應用,應用在專案本身無需關聯這個非模組的程式集。

自定義模組方法

模組中也可以有一些被其他依賴模組所使用的自定義方法。假設MyModule2依賴於MyModule1並想要在PreInitialize 方法中呼叫MyModule1的方法:

public class MyModule1 : AbpModule
{
    public override void Initialize()
    {
        IocManager.RegisterAssemblyByConvention(
        Assembly.GetExecutingAssembly());
    }
    public void MyModuleMethod1()
    {
        //this is a custom method of this module
    }
}
[DependsOn(typeof(MyModule1))]
public class MyModule2 : AbpModule
{
    private readonly MyModule1 _myModule1;
    public MyModule2(MyModule1 myModule1)
    {
        _myModule1 = myModule1;
    }
    public override void PreInitialize()
    {
        _myModule1.MyModuleMethod1(); //Call MyModule1's method
    }
    public override void Initialize()
    {
        IocManager.RegisterAssemblyByConvention(
        Assembly.GetExecutingAssembly());
    }
}

這裡我們將建構函式注入MyModule1到MyModule2,因此MyModule2可以呼叫MyModule1的自定義方法。僅當Module2依賴於Module1時才可以這樣做。

模組配置

雖然可以使用自定義模組方法配置模組,但建議使用配置系統來定義和設定模組的配置。

模組生命週期

模組類被自動註冊為單例模式。

https://aspnetboilerplate.com/Pages/Documents/Module-System

2020-10-18,望技術有成後能回來看見自己的腳步