【ABP框架系列學習】模塊系統(4)

0.引言

ABP提供了構建模塊和經過組合模塊以建立應用程序的基礎設施。一個模塊能夠依賴於另一個模塊。一般,程序集能夠認爲是模塊。若是建立多個程序集的應用程序,建議爲每一個程序集建立模塊定義。安全

當前,模塊系統主要集中在服務器,而不是客戶端。服務器

1.模塊定義

模塊是從ABP包中的AbpModule派生的類定義的。好比說開發一個能夠用於不一樣應用程序的博客模塊(Blog Module)。最簡單的模塊定義以下 :app

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

模塊定義類負責經過依賴注入註冊類,若有必要(能夠像上述事例按慣例完成)。它還能夠配置應用程序和其它模塊,給應用程序增長新的功能等等。框架

2.生命週期方法

ABP在程序啓動和關閉時調用模塊一些特定的方法。你能夠重寫這些方法以執行某些特定的任務。ide

ABP按照依賴順序調用這些方法。若是模塊A依賴模塊B,那麼模塊B在模塊A以前初始化。函數

啓動方法執行準確的順序:PreInitialize-B, PreInitialize-A, Initialize-B, Initialize-A, PostInitialize-B, PostInitialize-A。對於全部依賴關係圖都是如此。關閉方法也是相似的,但順序相反。ui

相關源碼:模塊啓動時依次執行PreInitialize()、Initialize()、PostInitialize(),模塊關閉時首先Reverse()、而後在逐個模塊Shutdown()。this

        public virtual void StartModules()
        {
            var sortedModules = _modules.GetSortedModuleListByDependency();
            sortedModules.ForEach(module => module.Instance.PreInitialize());
            sortedModules.ForEach(module => module.Instance.Initialize());
            sortedModules.ForEach(module => module.Instance.PostInitialize());
        }

        public virtual void ShutdownModules()
        {
            Logger.Debug("Shutting down has been started");

            var sortedModules = _modules.GetSortedModuleListByDependency();
            sortedModules.Reverse();
            sortedModules.ForEach(sm => sm.Instance.Shutdown());

            Logger.Debug("Shutting down completed.");
        }

PreInitialize

當應用程序啓動時,首先調用該方法。它是框架和其它模塊初始化以前配置它們的首選方法。spa

你還能夠在該方法中編寫特定的代碼,以便在依賴注入註冊以前運行。例如,若是你建立一個傳統的註冊類,那麼你應在該方法中使用IOCManager.AddConventionalRegisterer方法註冊它們。插件

Initialize

該方法是依賴注入註冊的地方,經過使用IocManager.RegisterAssemblyByConvention方法完成註冊。若是想定義自定義的依賴註冊,請見後續依賴注入章節。

PostInitialize

該方法在程序啓動的最後調用。在這裏解析依賴是安全的。

Shutdown

該方法在程序關閉時調用。

3.模塊依賴(Module Dependencies)

一個模塊能夠依賴於另外的模塊。你能夠經過DependsOn特性顯示聲明依賴項,以下代碼:

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

上述事例代碼中,聲明瞭MyBlogApplicationModule模塊依賴於MyBlogCoreModule模塊,那麼MyBlogCoreModule模塊應該在MyBlogApplicationModule模塊以前完成初始化。

ABP能夠從啓動模塊(start module)開始就遞歸的解析依賴關係,並相應地初始化它們。啓動模塊(start module)是最後進行初始化的模塊。

4.插件模塊

雖然模塊從啓動模塊開始查找並遍歷依賴關係,ABP還能夠動態加載模塊。AbpBootstrapper類中定義了PlugInSources屬性,該屬性可用於向動態加載的插件模塊添加源。插件源能夠是實現IPlugInSource接口的任何類。經過實現FolderPlugInSource類以從指定文件夾中的程序集獲取插件模塊。

ASP.NET CORE

ABP中ASP.NET CORE模塊在AddAbp擴展方法中定義選項,用於在啓動類中添加插件源:

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

也可使用更簡單的語法AddFolder擴展方法:

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

ASP.NET MVC,Web API

對於傳統的ASP.NET MVC應用程序,能夠經過重寫global.asax文件中Application_Start方法添加插件文件夾,以下代碼:

public class MvcApplication : AbpWebApplication<MyStartupModule>
{
    protected override void Application_Start(object sender, EventArgs e)
    {
        AbpBootstrapper.PlugInSources.AddFolder(@"C:\MyPlugIns");
        //...
        base.Application_Start(sender, e);
    }
}

Controllers in PlugIns

若是你的模塊包括MVC或Web API Controolers,ASP.NET不能查找你的控制器。爲了克服這個問題,你能夠修改global.asax文件,以下代碼:

using System.Web;
using Abp.PlugIns;
using Abp.Web;
using MyDemoApp.Web;

[assembly: PreApplicationStartMethod(typeof(PreStarter), "Start")]

namespace MyDemoApp.Web
{
    public class MvcApplication : AbpWebApplication<MyStartupModule>
    {
    }

    public static class PreStarter
    {
        public static void Start()
        {
            //...
            MvcApplication.AbpBootstrapper.PlugInSources.AddFolder(@"C:\MyPlugIns\");
            MvcApplication.AbpBootstrapper.PlugInSources.AddToBuildManager();
        }
    }
}

附加程序集(Additional Assemblies)

默認實現IAssemblyFinder和ITypeFinder接口只能在這些程序集中查找模塊程序集和類型。也能夠在模塊中重寫GetAdditionalAssembliesy方法來包括其它程序集。

自定義模塊方法(Custom Module Methods)

你的模塊還能夠擁有自定義的方法,並能在依賴於這個模塊的其它模塊中調用這個方法。假設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中的自定義方法,前提是MyModule2依賴於MyModule1。

模塊配置(Module Configuration)

然而自定義方法能夠用來配置模塊,建議使用啓動配置(startup configuration)系統來定義和設置模塊的配置。

模塊生命週期(Module Lifetime)

模塊類自動註冊爲單實例對象(singleton)。

相關文章
相關標籤/搜索