ABP官網:https://www.abp.io/
ABP GitHub:https://github.com/abpframework/abp
要學習ABP,第一手資料肯定是官方文檔,詳細信息也請查看官方文檔。
基本概念
ABP vNext(以下簡稱ABP)的前身是asp.net boilerplate(老版abp),它不是一個簡單的版本更新,而是完全基於.NET Core的重寫,廢話不多說,來到這里你至少是知道ABP的。
ABP是一個開源應用程序框架,專注於基於ASP.NET Core的Web應用程序開發,但也支持開發其他類型的應用程序。
計划從基礎搭建開始,逐步把涉及到的東西都走一遍,這將會是一個持續更新的系列文章。
本篇核心:
- 模塊化(Modularity)
- 依賴注入(Dependency Injection)
使用ABP開發新項目的最簡單方法是使用啟動模板,但我不打算這么干,我更想知道abp是怎么啟動的,我們不僅要知其然,更要知其所以然。
那么我們從一個空項目開始,手動安裝abp框架。
ABP開發.Net Core Console應用程序
1、使用Visual Studio創建一個新的.Net Core Console應用程序,就叫MyFirstAbpConsole。
2、添加引用Volo.Abp.Core

下面我們就引入abp的第一個重要的概念,模塊化(Modularity),abp是一個模塊化的框架,一個abp框架至少要包含一個模塊(從AbpModule類派生的模塊類),即啟動模塊或者叫根模塊。
3、創建一個模塊類MyFirstAbpConsoleAppModule,並繼承自AbpModule,這樣一個模塊就有了,暫時我們什么也不做,如下所示:

4、回到Program類的Main方法中,我們來啟動abp。
abp框架中提供了一個應用程序工廠類,用於創建啟動模塊,代碼如下:

這樣我們就創建並啟動了我們的模塊應用並且完成了初始化。
4、新建一個HelloWorldService的服務類,里面定義了一個SayHello的方法,代碼如下:

那么我們怎么調用我們的這個服務呢,這里又引入了一個重要的概念,依賴注入(Dependency Injection)。
在abp中,服務都會被注冊到容器中,在需要用到時注入該服務。
首先,把服務注冊到容器中,我們暫時先說一種方式,即繼承自ITransientDependency接口(瞬態的,不同生命周期后面再說),框架會自動把服務注冊到容器中
代碼如下:

5、獲取服務並調用服務輸出Hello World
回到Program類的Main方法,前面我們應用已經創建並初始化完成,接着我們調用服務如下:

這里我們使用了IServiceProvider接口來獲取服務,在abp中注入服務的方式有多種,后面再說。
6、運行程序,結果輸出Hello World 說明整個程序框架運行成功。

總結:
- abp是一個基於模塊化的框架,啟動並運行abp框架,至少要包含一個啟動模塊
- abp中的服務都是通過注入的方式調用,需要某個服務時不再需要new
- abp中的自動注冊服務的接口有三個,區別是生命周期不同,分別是ITransientDependency、IScopedDependency和ISingletonDependency
下面我們來改造下上面的依賴注入,我們來使用Autofac手動注冊服務
第一步,添加Volo.Abp.Autofac引用

第二步,回到MyFirstAbpConsoleAppModule模塊類,添加依賴項,把Autofac模塊添加到當前模塊中來(abp是基於模塊化的,所以Autofac對於abp來說也是一個模塊)

第三步,原先的 HelloWorldService繼承的接口ITransientDependency將不再需要,我們來使用Autofac手動把HelloWorldService注入到當前模塊中,需要我們來重寫AbpModule中的ConfigureServices虛方法,代碼如下:

第四步,創建模塊的代碼也要修改下,增加一個options操作,使用Autofac,如下:

第五步,我們再次運行程序,結果輸出Hello World 沒有問題。
至此,我們知道了如何創建一個abp的模塊、初始化應用、創建服務、注冊服務以及如何注入服務的一個最簡單流程。
本次內容的重點是理解模塊化、依賴注入兩個知識點,這兩點真的很重要,我們再展開聊聊
第一點:abp把應用進行了模塊化,每個模塊里定義自己的服務,並在它自己的獨立模塊類中通過依賴注入進行注冊。
public class SomeModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { //在這里注冊依賴項 } }
比如上面我們使用Autofac框架時,Autofac本身自己就是一個獨立模塊,然后我們使用它,就引入它,並且注冊到我們的模塊中,就是這么個意思

abp框架很龐大,但是不臃腫,因為我們按需分配,我們只引入並注冊的是我們需要的。
第二點:abp的依賴注入系統,是基於微軟的 dependency injection extension 庫(Microsoft.Extensions.DependencyInjection nuget package)開發的,因此,它的文檔在abp中也是有效的。
abp框架提供了多種注冊方式,主要是兩大類,一種是按約定的自動注冊,一種是手動注冊。這里簡單講一下,詳細可以看官方文檔。
常規注冊
abp引入了常規服務注冊,你不需要按照約定去做任何事情去注冊一個服務,它是自定完成的。如果你想禁用它,你可以通過重寫PreConfigureServices方法設置SkipAutoServiceRegistration = true即可。一旦跳過自動注冊,你就應該手動的注冊你的所有的服務,在這種情況下,擴展方法AddAssemblyOf能夠幫助你按照約定注冊你的所有服務,看個例子:
public class AppModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) { SkipAutoServiceRegistration = true; } public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAssemblyOf<AppModule>(); } }
固有的注冊類型
默認情況下,某些特定的類型已經注冊到依賴注入中
比如,上面的模塊類就是作為單例(singleton)注冊的,無需我們手動處理。
依賴接口注冊
如果你實現了這些接口,你的類就會自動的注冊到依賴注入中。比如上面我們首先使用的方式就是這種方式。
- ITransientDependency:注冊為瞬態生命周期,每次調用都是一個新的實例
- IScopedDependency:注冊為一個范圍內的生命周期,同一個http請求的范圍內使用的同一個實例
- ISingletonDependency:注冊為單例模式,首次請求會創建這個服務,后續的所有請求都使用相同的實例,存在於整個應用程序的生命周期中。
依賴特性注冊
是使用屬性DependencyAttribute,例子:
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)] public class SomeService { …… }
手動注冊
也可以通過手動方式注冊你需要的服務,上面已經用到了,就是在模塊類中的重寫配置服務的方法中手動添加,這種其實是微軟的標准的注入方式。
注入依賴項
如何調用已注冊的服務呢,abp提供了三種常見的方式
- 構造函數注入,這是將服務注入類的最常見方法
- 屬性注入,這點微軟是不支持的,abp可以與第三方DI提供程序(Autofac)集成,從而可以實現屬性注入
- 從IServiceProvider解析服務,即通過注入IServerProvider到類中,然后通過它來獲取服務,使用的很少
關於更多的如何注冊服務到容器以及將容器中的服務注入類的問題,請查看abp官方文檔和微軟的依賴注入的文檔吧。
通過上面的內容,我們已經通過一個控制台項目了解到如何運行abp框架,以及它的一些基本概念,現在,我們將基於Asp.Net Core Web 應用,繼續了解下abp框架如何在Web項目中工作。
ABP創建Asp.Net Core Web MVC應用程序
1、創建一個Asp.Net Core Web 應用程序MyFirstAbpWeb,使用空模板
2、添加引用:Volo.Abp.AspNetCore.Mvc
3、新建一個MyFirstAbpWebModule模塊類,因為是.NetCore的 MVC項目,所有添加一個依賴。
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Modularity; namespace MyFirstAbpWeb { [DependsOn(typeof(AbpAspNetCoreMvcModule))] public class MyFirstAbpWebModule : AbpModule { } }
4、配置啟動應用程序和初始化應用程序
4.1、打開Startup啟動類,在ConfigureServices方法中增加一段代碼,把剛剛新建的模塊類注冊進來(創建啟動模塊)。
public void ConfigureServices(IServiceCollection services) { services.AddApplication<MyFirstAbpWebModule>(options => { }); }
4.2、配置應用程序初始化,繼續修改Startup啟動類,在Configure方法中增加一行代碼,並且把原來的代碼剪切出來
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.InitializeApplication(); }
回到模塊類中,重寫OnApplicationInitialization方法,把剪切的內容粘貼過來,並稍作修改
using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Hosting; using Volo.Abp; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Modularity; namespace MyFirstAbpWeb { [DependsOn(typeof(AbpAspNetCoreMvcModule))] public class MyFirstAbpWebModule : AbpModule { public override void OnApplicationInitialization(ApplicationInitializationContext context) { var env = context.GetEnvironment(); var app = context.GetApplicationBuilder(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); //app.UseEndpoints(endpoints => //{ // endpoints.MapGet("/", async context => // { // await context.Response.WriteAsync("Hello World!"); // }); //}); app.UseConfiguredEndpoints(); } } }
5、配置完成后,新建一個控制器文件夾Controllers,在里面新建一個HomeController,繼承自AbpController
using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc; namespace MyFirstAbpWeb.Controllers { public class HomeController : AbpController { public ActionResult Index() { return Content("Hello World"); } } }
運行后,瀏覽器輸出Hello World
至此,我們使用了一個最基本的abp框架 ,后面我們將進入一個實戰階段
