ABP VNext系列(一)-第一个ABP VNext
下一篇 : ABP VNext系列(二)-详解ABP的依赖注入
目录
一. ABP VNext基本介绍
1. 什么是ABP VNext?
1. ABP框架全称为“ASP.NET Boilerplate Project”,中文翻译为“ ASP.NET样板项目”
2. 是由国外的十几名顶级架构师共同创立并开源到github(https://github.com/aspnetboilerplate)的
3. 目的是为了让.net 开发着能拥有一套开箱即用的项目架构.
4. 内部整合了一些常用的功能,比如orm、缓存、日志等等功能,让框架的使用者只需要关注业务逻辑,
而不需要关注其他多余的中间件功能
5. 上面介绍的是ABP,但是ABP VNext是啥呢?ASP.NET Boilerplate Project是基于.net framework开发的,
而ABP VNext则是作为.net core为基础的延申框架.
6. 总的来说就是,
ASP.NET Boilerplate Project是.net framework的版本框架,
ABP VNext是.net core版本的框架
7. ABP VNext:
github: https://github.com/abpframework/abp
官方文档: https://docs.abp.io/en/abp/latest
2. 用还是不用ABP VNext?
1. 至于为什么要用ABP VNext,博主也只能根据自身的使用经验来稍稍总结一下
2. 使用经验来看:
2.1 框架本身是按照DDD(领域驱动)来设计的,那么咱们再接入的过程中也*可以*按照DDD的思想来开发自己的
项目,利于后期项目的维护
2.2 这是一个模块化的框架,以模块来分基础功能.比如缓存模块,orm模块,就做到要啥拿啥的那种效果
2.3 代码量来说的话,再某些方面极大的减少了我们的代码量,比如对数据库的单表的增删查改方法内置了
都不需要自己写,直接用就行.但是在另一方面也会增加咱们的代码量.
2.3.1 比如aotumapper的配置
2.3.2 dto类的原来越多
2.3.4 一个很简单没有任何逻辑可言的查询都需要service+repository双层的接口和实现
2.4 业内通用功能不需要自己开发,只需要接入即可,很方便
3. 介绍不完了,反正这个框架有利有弊,需要自己平衡使用.但是针对微服务场景,ABP VNext能达到意想不到的效果
4. 并且这个是一个完整的大的框架,有一定的学习成本.而且如果用不好也会出问题.所以是否使用还是取决于自己.
二. 创建基于ABP VNext的项目
1. 使用之前需要掌握的技术
1. .net core肯定是必须的,博主会基于.net core 3.1的版本来介绍
2. ioc这个概念要知道是啥,并且工作中用到过,如果知道原理更佳.
3. .net core的IServiceCollection/ IServiceProvider的正确理解
4. ABP项目的一个完整的生命周期:
3.1 ABP项目和咱们普通的项目不一样,他是包含一个自己的运行生命周期的
3.2 步骤大概是: 生命周期开始前的配置 --> 生命周期配置完成后的初始化 -->
生命周期初始化完成后稳定运行 --> 生命周期结束
3.3 这么介绍有点太抽象,难以理解.不过不影响接下来的步骤进行,只需要大概知道有这么个东西存在即可
3.4 ABP项目的生命周期是以一个[模块]为基础的,那么每一个项目都是一个模块,并且有一个启动模块
5. 博主下面的三个实例需求场景:
4.1 有一个接口ITest,包含一个RunAsync()的方法.
4.2 Test实现类继承ITest接口并打印点东西
4.3 基于ABP项目运行并调用RunAsync()方法
6. 下面博主就来借助下面三种项目类型来完成一个最小化的ABP项目,包含一个ABP项目的完整生命周期
----这个作为咱们下面项目的简单接口和实现类
public interface ITest
{
Task RunAsync(string str);
}
public class Test : ITest
{
public async Task RunAsync(string str)
{
Console.WriteLine($"[接收打印]:{str}");
await Task.CompletedTask;
}
}
2. 控制台宿主
- 基于上面的接口和实现来,咱们先来考虑一个场景
- 假设我们需要在Console控制台调用此方法,正常情况下是一个什么样的流程.如下图
- 上面就是最基本的调用方式,那么我说过ABP是有一套自己独立的生命周期的,那么接下来我们看看
ABP需要怎么做
3.1 首先我们需要引入ABP相关的包Volo.Abp.Core(核心包)
和Volo.abp.Autofac(Ioc容器包)
因为项目是基于.net core 3.1的,所以包的版本都是3.3.2
3.2 上面简单介绍过,ABP是一个模块化的框架,并且ABP生命周期启动是依赖于一个独立的启动
模块的,所以接下来我们要为控制台创建一个启动模块
//1. 模块其实对应的就是一个继承于 AbpModule的一个普通类
//2. AbpModule是Volo.Abp.Core包里面的一个核心类
//3. 由于我们需要用到Autofac,需要引用一下Autofac的模块
[DependsOn(typeof(AbpAutofacModule))]
//4. 就这样,控制台的启动模块我们就写完了,是不是很简单
[DependsOn(typeof(AbpAutofacModule))]
public class TestModule : AbpModule
{
}
- 到这一步,或许大家有疑问了,一个空类有啥作用?为啥需要这个东西?别着急,后面的文章将会详细的介绍[模块类]
- 接下来我们来看看怎么用ABP来完成上面的接口调用
******注意*****
//此时需要在Test实现类后面继承一个ITransientDependency接口
public class Test : ITest, ITransientDependency
static async Task Main(string[] args)
{
//1.这行代码就是创建一个ABP的应用的标准代码
//2.返回的是一个ABP应用的对象
//3.其中`UseAutofac()`扩展方法是为了帮我们实现自动注册接口
//4.ITransientDependency 就是一个协助自动注册的约定接口
using var application = AbpApplicationFactory.Create<TestModule>(options => options.UseAutofac());
//上面代码拿到一个ABP应用对象之后需要对这个进行初始化
application.Initialize();
//1.初始化成功之后,通过下面方法可以拿到我们的接口对象
//2.ServiceProvider其实就是.net core中的IServiceProvider对象
//3.GetRequiredService<T>()方法可以帮我们拿到注册的接口对象
var test = application.ServiceProvider.GetRequiredService<ITest>();
//1.拿到ITest对象之后就可以直接执行了
//2.运行之后会发现和预期结果是一致的
await test.RunAsync("111");
}
- 到这里,我们就完整的创建了一个控制台宿主的ABP应用程序
3. WokerService宿主(后台服务项目)
//这个是咱们一个服务项目创建出来之后的初始代码,很简单的逻辑
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();//将woker类设置为启动项目
});
//1. 首先还是要创建一个模块类,继承AbpModule,并引用Autofac模块
//2. 重写一个方法,并将Program类中的AddHostedService方法移到这里来
//3. 这样我们的启动模块就完成了
//4. 但是改造还没结束...
[DependsOn(typeof(AbpAutofacModule))]
public class WorkerHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddHostedService<Worker>();
}
}
//改造我们我们Program中的方法,让其接入ABP的生命流程管理
public static void Main(string[] args)
{
//1. 获取build对象,不要直接调Run()方法,目的是为了,并且初始化
var build = CreateHostBuilder(args).Build();
//2. 拿到ABP应用的对象
var application = build.Services.GetRequiredService<IAbpApplicationWithExternalServiceProvider>();
//3. ABP应用初始化,执行Initialize
application.Initialize(build.Services);
//4. 调用Run()方法使程序跑起来
build.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
//这里需要将启动类配置进行后置 -->到模块类中
services.AddApplication<WorkerHostModule>();
})
.UseAutofac();//引用Autofac
//接下来改造我们的Worker类
public class Worker : BackgroundService
{
private readonly ITest _test;//注入我们的ITest接口
public Worker(ITest test)
{
this._test = test;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (true)
{
//直接调用即可
await this._test.RunAsync(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
await Task.Delay(500, stoppingToken);
}
}
}
4. Web宿主
- 创建一个空的api项目,并引入
Volo.Abp.AspNetCore.Mvc
和Volo.abp.Autofac
- 继续创建一个模块启动类
//1. 这次我们需要多引用两个模块
//2. 重写一个方法,把原来的Startup类中的方法拿到这里来,并删除多余的
[DependsOn(
typeof(AbpAutofacModule),
typeof(AbpAspNetCoreModule),
typeof(AbpAspNetCoreMvcModule)
)]
public class WebHostModule : AbpModule
{
/// <summary>
/// abp 模块初始化
/// </summary>
/// <param name="context"></param>
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseConfiguredEndpoints();
}
}
- 改造Program类
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac();//只是增加了这一行代码
- 改造Startup类
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//添加一个ABP模块应用
services.AddApplication<WebHostModule>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//1. 多余方法全部移除或者放到WebHostModule中初始化
//2. 调用app的初始化方法
//3. 这个类改造比较固定
app.InitializeApplication();
}
}
- 改造一下Test
public class Test : ITest, ITransientDependency
{
//这里我们返回一个字符串,方便Api测试
public async Task<string> RunAsync(string str)
{
await Task.CompletedTask;
return $"[接收打印]:{str}";
}
}
- 控制器
[ApiController]
public class TestController : ControllerBase
{
private readonly ITest _test;//注入我们的方法
public TestController(ITest test)
{
this._test = test;
}
[HttpGet]
[Route("home/get")]
public async Task<IActionResult> Get(string str)
{
//通过api来测试是否正常
return new JsonResult(await this._test.RunAsync(str));
}
}
- 运行
- 到这里,我们web项目也集成了ABP
三. 总结
1. 此测试实例代码放在 https://gitee.com/jerryow/abp-practice
2. 此文介绍的是最小化的ABP应用,但是工作中是基于DDD的分层架构来搭建多层项目的,所以这个实例仅仅
是为了帮助入门理解而已
3. ABP帮助我们进行了约定式的Ioc注册.比如我们的ITest接口的获取是并没有手动注册到容器的,
而是通过在实现类中继承了一个ITransientDependency的接口就实现了自动注册.
4. 博主之前的文章有开启一个基于ABP VNext的微服务架构系列文章,但是写到第二节发现,并不适合所有人阅读.
因为涉及到的内容实在是太多了,比如:
4.1 ABP框架的应用和各个应用模块的使用
4.2 微服务架构中的相关中间件: 网关、服务发现注册、配置中心、缓存、消息队列、认证授权中心、日志等
4.3 微服务架构中的部署相关: git、jenkins、docker、k8s
4.4 微服务架构中的性能监控: promethus、skywalking
5. 众多原因让博主不得不放弃直接继续写那个文章,所以博主改变了方式,会先介绍这些相关的组件还有
聚焦到ABP框架的本身
6.最后再进行基于ABP VNext的微服务架构系列文章的完善.