ABP+AdminLTE+Bootstrap Table權限管理系統第三節--abp分層體系,實體相關及ABP模塊系統

 

 

返回總目錄:ABP+AdminLTE+Bootstrap Table權限管理系統一期html

ABP模塊系統 

說了這麼久,尚未詳細說到abp框架,abp其實基於DDD(領域驅動設計)原則的細看分層以下:前端

再看咱們項目解決方案以下:web

JCmsErp.Application,應用層:進行展示層與領域層之間的協調,協調業務對象來執行特定的應用程序的任務。它不包含業務邏輯,主要包含一些模型,abp重要的數據傳輸DTO,包括數據庫映射實體,前端視圖模型轉實體(Entity)對象,一個應用服務方法一般被認爲是一個工做單元(Unit of Work),使用一種像AutoMapper這樣的工具來進行實體與DTO之間的映射,前端參數傳入有限性驗證等等數據庫

JCmsErp.Core:領域層:領域層就是業務層,是一個項目的核心,全部業務規則都應該在領域層實現。包括業務對象和業務規則,這是應用程序的核心層。 設計模式

實體(Entity):實體表明業務領域的數據和操做,在實踐中,經過用來映射成數據庫表。併發

倉儲(Repository):倉儲用來操做數據庫進行數據存取。倉儲接口在領域層定義,而倉儲的實現類應該寫在基礎設施層。app

領域服務(Domain service):當處理的業務規則跨越兩個(及以上)實體時,應該寫在領域服務方法裏面。框架

領域事件(Domain Event): 在領域層某些特定狀況發生時能夠觸發領域事件,而且在相應地方捕獲並處理它們。 ide

工做單元(Unit of Work)工做單元是一種設計模式,用於維護一個由已經被修改(如增長、刪除和更新等)的業務對象組成的列表。它負責協調這些業務對象的持久化工做及併發問題。
函數

JCmsErp.EntityFramework:基礎設施層:提供通用技術來支持更高的層。例如基礎設施層的倉儲(Repository)可經過ORM來實現數據庫交互。當在領域層中爲定義了倉儲接口,應該在基礎設施層中實現這些接口。可使用ORM工具,例如EntityFramework或NHibernate。ABP的基類已經提供了對這兩種ORM工具的支持。還有數據遷移等。

JCmsErp.Web:展示層:提供試圖用於與用戶實現交互操做.

JCmsErp.WebApi:這裏在abp中主要是提供接口,能夠是解決方案內部使用接口,能夠是與移動端等其餘端口鏈接的接口.

二,實體(Entity)

實體是DDD(領域驅動設計)的核心概念之一。Eirc Evans是這樣描述的實體的:「它根本上不是經過屬性定義的,而是經過一系列連續性和標識定義的」。所以,實體都有Id屬性而且都存儲到數據庫中。一個實體通常會映射到數據庫的一張表

abp中實體是派生於Entity類,先看一下咱們在Core層新建的Users類

Users實體類,有人說這個實體爲何沒有id,由於Users繼承自Entity類,Entity類已經定義id,

它是該Entity類的 主鍵。所以,全部實體的主鍵名都是相同的,都是Id

Id(主鍵)的類型是能夠改變的,默認是int(int32)的。若是你想將Id定義爲其餘類型,能夠在<>內寫,好比Guid,long也是能夠的。

Entity類重寫了等號運算符(==),能夠輕鬆地檢查兩個實體是否相同了(實體的Id相同則認爲它們相同)。它也定義了IsTransient方法來檢測它是否有Id。

 

 

審計:

IHasCreationTime使得使用一個通用的屬性來描述一個實體的「建立時間」信息成爲可能。當實現了該接口的實體類插入到數據庫中時,ABP會自動地將當前的時間設置給CreationTime。

ICreationAudited增長了CreatorUserId擴展了IHasCreationTime,當用戶保存一個新的實體的時候,會自動把當前的id設置爲CreatorUserId,還有相似的LastModificationTime也是同樣。

當更新實體時,abp會自動爲你設置這些屬性。

軟刪除

軟刪除是將一個實體標記爲已刪除的一般使用的模式,而不是直接從數據庫中刪除。好比,你可能不想從數據庫中硬刪除一個User,由於它可能關聯其餘的表

ABP實現了開箱即用的軟刪除模式。當一個軟刪除實體被刪除後,ABP檢測到以後,會阻止刪除,將IsDeleted設置爲true並更新數據庫中的實體。並且,它會自動地過濾數據庫中軟刪除的實體,不會檢索(select)它們。

若是使用了軟刪除,那麼你可能想存儲一些信息,好比什麼時候刪除以及誰刪除了一個實體等等

 

 

在JCmsErp.Application建立一個Users文件夾,而後建立UserinfoDto,DTO是用於Core和 Web間的數據傳輸對象.有了實體了爲何還要DTO呢

1,DTO保證了層與層的分離,web層改變不影響core層,core作改變也不影響web.

2,數據保護,否則敏感或者不須要的數據暴露於web層,不被別人窺見如密碼,銀行帳號,身份證等敏感信息

3,序列化,序列化集合,可是子集不序列化,當首次用到子集的時候才序列化.

4,惰性加載

5,DTO數據驗證

6,abp還有一些擴展的接口,擴展性好,下降耦合度,使表現層和邏輯層之間耦合度下降.

這裏Serializable就是支持序列化的標籤,   [AutoMapFrom(typeof(Users))]是指和Users之間雙向自動轉化的標籤,並不須要每一個字段都去手動匹配.ABP提供了若干特性和擴展方法來定義映射。首先,要將Abp.AutoMapper nuget包添加到項目中。而後,AutoMap特性是雙向映射方式, AutoMapFrom和 AutoMapTo是單向映射方式。最後,使用MapTo擴展方法將一個對象映射到另外一個對象

ABP模塊系統簡介

ABP框架提供了建立和組裝模塊的基礎,一個模塊可以依賴於另外一個模塊。在一般狀況下,一個程序集就能夠當作是一個模塊。在ABP框架中,一個模塊經過一個類來定義,而這個類要繼承自AbpModule。

模塊系統當前專一於服務端而不是客戶端。


若是學習過Orchard的朋友,應該知道module模塊的強大了。模塊的本質就是可重用性,你能夠在任意的地方去調用,並且經過實現模塊,你寫的模塊也能夠給別人用。.net能夠經過反射獲取一個程序集中的類以及方法。

1.3.2 定義模塊

Assembly程序集:Assembly是一個用來包含程序的名稱,版本號,自我描述,文件關聯關係和文件位置等信息的一個集合。最簡單的理解就是:一個你本身寫的類庫生成的dll就能夠看作是一個程序集,這個程序集能夠包括不少類,類又包括不少方法等。

一個派生自 AbpModule 的類就是模塊的定義。咱們正在開發一個博客模塊,該模塊能夠被使用在不一樣的應用程序中。最簡單的模塊定義示例以下:

public class MyBlogApplicationModule : AbpModule //定義
{
    public override void Initialize() //初始化
    {
        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
        //這行代碼的寫法基本上是不變的。它的做用是把當前程序集的特定類或接口註冊到依賴注入容器中。
    }
}

 

若是須要的話,模塊類負責類的依賴注入(一般能夠像上面同樣作)。咱們能配置應用程序和其它模塊,添加新的功能到應用程序等等。

1.3.3 方法的生命週期

在一個應用中,ABP框架調用了Module模塊的一些指定的方法來進行啓動和關閉模塊的操做。咱們能夠重載這些方法來完成咱們本身的任務。

ABP框架經過依賴關係的順序來調用這些方法,假如:模塊A依賴於模塊B,那麼模塊B要在模塊A以前初始化,模塊啓動的方法順序以下:

  1. PreInitialize-B
  • PreInitialize-A
  • Initialize-B
  • Initialize-A
  • PostInitialize-B
  • PostInitialize-A

下面是具體方法的說明:

PreInitialize

預初始化:當應用啓動後,第一次運行會先調用這個方法。在初始化(Initialize)方法調用以前,該方法一般是用來配置框架以及其它模塊。

在依賴注入註冊以前,你能夠在這個方法中指定你須要注入的自定義啓動類。例如:加入你建立了某個符合約定的註冊類,你應該使用 IocManager.AddConventionalRegisterer 方法在這裏註冊它。

Initialize

初始化:在這個方法中通常是來進行依賴注入的註冊,通常咱們經過IocManager.RegisterAssemblyByConvention這個方法來實現。若是你想實現自定義的依賴注入,那麼請參考依賴注入的相關文檔。

PostInitialize

提交初始化:最後一個方法,這個方法用來解析依賴關係。

Shutdown

關閉:當應用關閉之後,這個方法被調用。

1.3.4 模塊依賴

Abp框架會自動解析模塊之間的依賴關係,可是咱們仍是建議你經過重載GetDependencies方法來明確的聲明依賴關係。

[DependsOn(typeof(MyBlogCoreModule))]//經過註解來定義依賴關係
public class MyBlogApplicationModule : AbpModule
{
    public override void Initialize()
    {
        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
    }
}

 

例如上面的代碼,咱們就聲明瞭MyBlogApplicationModule和MyBlogCoreModule的依賴關係,MyBlogApplicationModule這個應用模塊依賴於MyBlogCoreModule核心模塊,而且,MyBlogCoreModule核心模塊會在MyBlogApplicationModule模塊以前進行初始化。

ABP能夠從 startup module 遞歸的解析依賴關係,並按需初始化它們。最後初始化的模塊是啓動模塊(startup module)。

1.3.5 插件模塊

當模塊從啓動模塊以及其依賴關係進行調查發現的時候,ABP也可以動態的加載其它指定模塊。AbpBootstrapper 類定義了 PlugInSources 屬性,咱們能用該屬性添加須要動態加載的模塊。插件源能夠是任何實現了 IPlugInSource 接口的類。FolderPlugInSource 類實現了該接口,它能夠被用來加載指定文件夾下的程序集。

ASP.NET Core

ABP的ASP.NET Core模塊也能夠動態加載模塊,你只須要在 Startup 類中使用已定義的擴展方法 AddAbp,以下所示:

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

 

咱們可使用擴展方法 AddFolder 更方便的實現上述功能:

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

 

瞭解更多關於Startup類的信息,請查看 ASP.NET 文檔

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);
    }
}

 

插件中的控制器

若是你的模塊包括了MVC或者Web API控制器,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的默認實現(這兩個接口的實現被ABP用來在應用程序中發現指定的類)僅僅只用來查找模塊程序集以及在這些程序集中所使用的類型。咱們能夠在咱們的模塊中重寫 GetAdditionalAssemblies 方法來包含附加程序集。

1.3.6 自定義的模塊方法

咱們本身定義的模塊中可能有方法被其餘依賴於當前模塊的模塊調用,下面的例子,假設模塊2依賴於模塊1,而且想在預初始化的時候調用模塊1的方法。這樣,就把模塊1注入到了模塊2,所以,模塊2就能調用模塊1的方法了。

譯者注:
ABP的模塊系統與Orchard的模塊有相似之處,但仍是有比較大的差異。Orchard的框架修改了ASP.NET程序集的默認加載方式(模塊的DLL沒有放在Bin文件夾下,是放在WEB項目根文件夾下面的Modules文件夾下),實現了功能模塊的熱插拔,而ABP的模塊程序集仍是放在Bin文件夾下的,沒有實現熱插拔。

public class MyModule1 : AbpModule
{
    public override void Initialize() //初始化模塊
    {
        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());//這裏,進行依賴注入的註冊。
    }

    public void MyModuleMethod1()
    {
        //這裏寫自定義的方法。
    }
}

[DependsOn(typeof(MyModule1))]
public class MyModule2 : AbpModule
{
    private readonly MyModule1 _myModule1;

    public MyModule2(MyModule1 myModule1)
    {
        _myModule1 = myModule1;
    }

    public override void PreInitialize()
    {
        _myModule1.MyModuleMethod1(); //調用MyModuleMethod1的方法。
    }

    public override void Initialize()
    {
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
     }
}

 

在這裏,咱們經過構造函數注入MyModule1到MyModule2,因此MyModule2可以調用MyModule1的自定義方法。當且僅當MyModule2依賴於MyModule1纔是可能的。

1.3.7 模塊配置

雖然自定義模塊能夠被用來配置模塊,可是,做者建議使用啓動配置來定義和配置模塊。

1.3.8 模塊生命週期

全部的模塊類都被自動的註冊爲單例模式。

 

返回總目錄:ABP+AdminLTE+Bootstrap Table權限管理系統一期

相關文章
相關標籤/搜索