前言:
本文使用 .NET Core SDK 3.1 的版本。
ABP Framework 在2013年就有了,至今为止出现过很多版本,
在.NET Core出现后,ABP 也发生了巨大的改变,当前版本早期为了与之前的版本进行区分叫做 Abp vNext,
现在Abp vNext已经成熟可以商用了,vNext 就不再存在,实际上他的名字就叫 ABP Framework。
一、创建ABP应用的方式
创建ABP应用有三种方式:
- 使用ABP的模板,按照官网指示安装 ABP CLI,使用 ABP CLI 创建项目
- 使用ABP的模板,直接在官网填写基本信息直接下载
- 在 Visual Studio 中创建 ASP.NET Core 新项目,引入 ABP 相关的包。
如果是快速开发可以使用 ABP 的模板,因为生成的项目比较复杂。如果想深入定制手动创建项目再引入 ABP 相关的包比较好。
二、运行基于ABP的控制台应用
创建一个基于 .NET Core 的控制台应用,可通过 Visual Studio 创建,也可以使用命令行创建。
> dotnet new console -n HelloAbp
引入所依赖的NuGet包,Microsoft.Extensions.DependencyInjection 和 Volo.Abp.Core。
> dotnet add package Microsoft.Extensions.DependencyInjection -v 5.0.1
> dotnet add package Volo.Abp.Core -v 4.3.3
一个Abp应用就至少需要一个模块,在Abp里面模块是以类的形式表现的,
创建一个名为 HelloAbpModule 的类,继承 AbpModule 类,这就是所谓的模块。
public class HelloAbpModule : AbpModule
{
}
模块本身是没有业务逻辑的,所以我们需要一个服务。
由于Abp使用了依赖注入,要在Abp中使用服务,就需要对相应的服务进行注册。
不过有些内容不需要我们手动注册,Abp可以按照约定去注册常见的服务类型,Abp可以通过接口实现自动注册。
创建一个 HelloAbpService.cs 服务,并实现 ITransientDependency 接口,使其在程序启动时自动注册。
public class HelloAbpService : ITransientDependency
{
public void Run() => Console.WriteLine("Hello Wordld");
}
修改 Main 函数使程序能够按照我们想要的方式执行。
static void Main(string[] args)
{
// 一个模块类代表一个模块,在一个项目里一般只有一个模块类,
// 通过启动模块来创建Abp的应用对象
var app = AbpApplicationFactory.Create<HelloAbpModule>();
// 初始化Abp应用对象
app.Initialize();
// 在应用对象的服务容器中拿到业务服务类
// 需要安装 Microsoft.Extensions.DependencyInjection 依赖注入的包
var service = app.ServiceProvider.GetService<HelloAbpService>();
service.Run();
}
三、运行基于ABP的Web应用
创建一个基于 .NET Core 的 ASP.NET Core Web API 项目,可通过 Visual Studio 创建,也可以使用命令行创建。
> dotnet new webapi -n Sample.Abp
引入所依赖的NuGet包 Volo.Abp.AspNetCore.Mvc。
> dotnet add package Volo.Abp.AspNetCore.Mvc -v 3.3.2
创建一个Abp的模块作为启动模块 AppModule 并继承 AbpModule,
public class AppModule : AbpModule
{
}
由于现在是基于Abp框架,
中间件管道的配置就不在Startup中配置了,而是转移到启动模块中进行配置。
如果要在启动模块中进行配置管道,
那么还需要为启动模块添加它所依赖的其他模块,通过特性 DependsOn 定义模块间的依赖关系
// 通过特性添加当前模块所依赖的其他模块
[DependsOn(typeof(AbpAspNetCoreMvcModule))]
public class AppModule : AbpModule
{
// TODO:
}
管道的配置在应用启动时进行,
在AbpModule中有一个名为 OnApplicationInitialization 的应用初始化方法,
一般在该方法中配置中间件管道 我们需要在AppModule中复写他,
public class AppModule : AbpModule
{
public override void OnApplicationInitialization(
ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
而现在的 Startup 职责是初始化Abp,
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<AppModule>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.InitializeApplication();
}
}
完成Abp框架的配置后,之后的开发基本完全一样。
如果想创建一个控制器,现在是继承 AbpController 而不是 ControllerBase,
由于使用了Abp的控制器,把管道中配置终结点的方法删掉换为Abp的提供的终结点方法。
public override void OnApplicationInitialization(
ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
// 替换默认的终结点
app.UseConfiguredEndpoints();
}
添加一个 基于 AbpController 的 Action。
public class HomeController : AbpController
{
public IActionResult Index()
{
return Content("Hello World");
}
}
本地启动项目,访问 ~/home/index 即可得到 Hello World 。
四、Abp中的注入
自动注入服务需要实现对应的接口,例如瞬时的需要实现 ITransientDependency
,而另外两个是 IScopedDependency
和 ISingletonDependency
。
public class HelloAbpService : ITransientDependency
{
public void Run() => Console.WriteLine("Hello Wordld");
}
或者使用特性
[Dependency(ServiceLifetime.Transient)]
public class HelloAbpService
{
public void Run() => Console.WriteLine("Hello Wordld");
}
手动注入和 ASP.NET Core 一样,依旧是在 IServiceCollection
对象中注入配置,
不过配置注入的位置不一样,需要重写 AbpModule 的 ConfigureServices 方法。
public class HelloAbpModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTransient<HelloAbpService>();
// context.Services.AddScoped<HelloAbpService>();
// context.Services.AddSingleton<HelloAbpService>();
}
}
五、模块的生命周期
一个模块的生命周期可以粗略分为 模块配置、模块初始化和模块销毁,如上图所示可以重写相应的方法。
在 ASP.NET Core 的 Startup 中的 ConfigureServices 与 AbpModule 的 ConfigureServices 相对应,
而 Startup 中的 Configure 与 AbpModule 的 OnApplicationInitialization 相对应。
关于模块的依赖关系
一个模块可能依赖于多个其他的模块,而他们之前的依赖关系决定了模块的加载和启动顺序,在Abp中使用了拓扑排序算法来计算模块的加载顺序。
启动流程
- 注册ABP基础设施与核心服务
- 加载整个应用的所有模块,按照依赖进行排序
- 按顺序遍历所有模块,执行每一个模块的配置方法(3个)
- 按顺序遍历所有模块,执行每一个模块的初始化方法(3个)