ABP入門系列目錄——學習Abp框架之實操演練
源碼路徑:Github-LearningMpaAbp
1. 引言
現在的互聯網已不在僅僅局限於網頁應用,IOS、Android、平板、智能家居等平台正如火如荼的迅速發展,移動應用的需求也空前旺盛。所有的互聯網公司都不想錯過這一次移動浪潮,布局移動市場分一份移動紅利。
的確,智能手機作為我們日常生活已必不可少的一部分,通過手機app能夠獲得更好的體驗,比如社交、購物、娛樂、生活。
但這也引入了一個問題,如果布局移動市場,就意味着要維護好幾條產品線,比如網頁、Android、IOS、微信公眾號等。這對公司來說無疑是一項大的投入。
產品對於用戶來說,用戶只關心體驗。
而對於開發者來說,開發者更關心在保證業務流程及數據的正確流轉下,如何對產品線進行集成,來避免做重復工作。
而恰好ABP框架就已經幫我們解決了這一問題,Abp是基於【模塊化設計思想】構建的,開發人員可以將自定義的功能以模塊(module)的形式集成到ABP中。
不同的模塊通過組裝就可以組成一個新的功能。
那你肯定很好奇如何玩轉Abp模塊,下面我們就以我們的Demo為例,來進行微信公眾號模塊的開發。
2. 創建微信公眾號模塊
定義一個模塊很簡單,只需創建微信項目,然后定義WeixinModule類繼承自AbpModule即可,再然后為WeixinModule定義[DependsOn]特性指定依賴的模塊即可。
2.1. 創建微信公眾號項目
新建mvc項目,命名項目名為LearningMpaAbp.Weixin。因為要使用到Abp定義的模塊功能,首先要安裝Abp Nuget包,選擇后會提示需要以下Nuget包,點擊確定安裝即可。
2.2. 定義微信公眾模塊
新建LearningMpaAbpWeixinModule繼承自AbpModule。代碼如下:
public class LearningMpaAbpWeixinModule:AbpModule
{
/// <summary>
/// 預初始化,通常是用來配置框架以及其它模塊
/// </summary>
public override void PreInitialize()
{
base.PreInitialize();
}
/// <summary>
/// 初始化,一般用來依賴注入的注冊
/// </summary>
public override void Initialize()
{
//把當前程序集的特定類或接口注冊到依賴注入容器中
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
/// <summary>
/// 提交初始化,一般用來解析依賴關系
/// </summary>
public override void PostInitialize()
{
base.PostInitialize();
}
/// <summary>
/// 應用關閉時調用
/// </summary>
public override void Shutdown()
{
base.Shutdown();
}
}
從代碼中可以看出主要包括四個重載方法,每個重載方法負責不同的職責。
2.3. 指定依賴模塊
因為我們需要通過webapi與現有demo進行交互,所以還需要安裝Abp.Web.Api Nuget包。
那怎樣指定依賴呢,只需要通過[DependsOn]特性指定即可。
[DependsOn(typeof(AbpWebApiModule))]
public class LearningMpaAbpWeixinModule:AbpModule
{
//....
}
好了,一個微信公眾號模塊的基礎項目框架搭好了,是不是很簡單!
到這一步,你可能會問,你這只是簡單創建微信公眾號模塊,但如何與我們Demo進行集成交互呢?
對的,是只簡單創建了微信模塊,但這一節我不打算講如何與Demo進行集成交互。因為在介紹如何通過webapi與系統交互之前,梳理下Abp模塊化的設計,更能幫助我們了解模塊化設計思想。
下面我們就簡單梳理下ABP模塊化的設計。
3. ABP模塊化設計
說到模塊,突然想到幾個單詞考考大家,model、modal、module分別是什么意思?
不知道的就自行查詞典吧。
下面回歸正題。
3.1. 模塊化相關類型
先來看看模塊相關類型依賴圖:
從類型依賴圖中可以看出設計的並不復雜:
- AbpModule:所有定義的模塊均需繼承此抽象類。
- AbpModuleInfo:可以理解為AbpModule的元數據,封裝AbpModule的基本信息,主要包括Assembly(所屬程序集)、Type(類型)、Dependencies(依賴的模塊)、IsLoadedAsPlugIn(是否插件模塊)。
- AbpModuleCollection:從類的申明:
class AbpModuleCollection : List
可知它是一個AbpModuleInfo的集合。 - AbpModuleManager:模塊管理類,主要用來進行模塊管理,比如啟動關閉模塊。
- DependsOnAttribute:依賴特性,用來標明模塊的依賴項。
3.2. Abp如何發現並加載模塊
Abp中定義了一個啟動類AbpBootstraper
,該類的職責是啟動整個Abp系統,主要負責依賴注入和注冊模塊以供啟動。而該類必須在應用程序啟動時最先被實例化。
而作為Abp生成的模板項目,啟動項目自然是web應用,所以AbpBootstrapper
肯定在Web項目中被初始化。眾所周知,web項目的啟動是從Global.asax文件的Application_Start
項目開始的。
public class MvcApplication : AbpWebApplication<LearningMpaAbpWebModule>
{
protected override void Application_Start(object sender, EventArgs e)
{
AbpBootstrapper.IocManager.IocContainer.AddFacility<LoggingFacility>(
f => f.UseAbpLog4Net().WithConfig("log4net.config")
);
base.Application_Start(sender, e);
}
}
我們先來觀察下類的申明,有沒有發現什么特別之處?
繼承的是泛型基類且指定的泛型為LearningMpaAbpWebModule
,指定了一個Module,當前web項目的Moduel。
對MVC比較熟悉的同學應該知道,MVC應用程序啟動類默認是繼承自HttpApplication
的。從該段代碼可以看出,Abp修改了MvcApplication
的默認繼承類。那自然AbpWebApplication<T>
是繼承自HttpApplication
了。廢話不多說,來看一看具體的定義:
public abstract class AbpWebApplication<TStartupModule>
: HttpApplication where TStartupModule : AbpModule
{
/// <summary>
/// Gets a reference to the <see cref="P:Abp.Web.AbpWebApplication`1.AbpBootstrapper" /> instance.
/// </summary>
public static AbpBootstrapper AbpBootstrapper { get; } = AbpBootstrapper.Create<TStartupModule>();
/// <summary>
/// This method is called by ASP.NET system on web application's startup.
/// </summary>
protected virtual void Application_Start(object sender, EventArgs e)
{
ThreadCultureSanitizer.Sanitize();
AbpWebApplication<TStartupModule>.AbpBootstrapper.Initialize();
}
/// <summary>
/// This method is called by ASP.NET system on web application shutdown.
/// </summary>
protected virtual void Application_End(object sender, EventArgs e)
{
AbpWebApplication<TStartupModule>.AbpBootstrapper.Dispose();
}
//省略了部分代碼
}
首先映入眼簾的是基類中定義的AbpBootstraper
屬性,然后看到的是Application_Start
和Application_End
虛方法。
Application_Start
方法中調用了AbpBootstrapper.Initialize()
方法。相當於AbpBootstrapper.Create<TStartupModule>().Initialize();
代碼是不是看累了,上圖,咱們直接來看web項目啟動時Module動態加載的調用堆棧。
是不是一目了然,總結以下:
Abp在啟動項目時根據指定的啟動模塊(StartupModule)首先加載該模塊,然后再去檢查該模塊的自定義特性是否定義有[DependsOn]特性,若有則按序加載所有依賴的模塊,也就是鏈式動態依賴加載。然后再依次調用Module的PreInitialize,Initialize和PostInitialize以完成初始化。
好了模塊的啟動加載就講到這里,感興趣的還是建議大家直接看看源碼。
這里推薦一篇文章ABP源碼分析三:ABP Module,來幫助大家理解Abp的模塊化思想。
4. 總結
這一節有點標題黨的味道,但內容也算點題了。下一篇我將介紹微信公眾號模塊如何通過WebApi與系統進行交互,盡情期待。