10

聊一聊ABP vNext的模块化系统

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzU0Mzk1OTU2Mg%3D%3D&%3Bmid=2247486223&%3Bidx=1&%3Bsn=4b42a854c9c0aa625553b0215f69d7ef
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
  • 官网

    https://abp.io/

  • 开源:

    https://github.com/abpframework/abp

  • EasyAbp:

    https://easyabp.io/

  • Abp 模块:

    https://abp.io/packages

模块化系统

f6NFNbu.png!mobile

ABP vNext 的世界观

在 Abp vNext 框架里面,模块系统是整个框架的基石,了解了模块系统以后,对于剩下的设计就很好理解了。

模块系统是就像上图乐高玩具一样,一块一块零散积木堆积起一个精彩的世界。每种积木的形状各不相同,功能各不相同,积木与积木直接互相依赖,互相支撑。

模块分两种类型.它们没有任何结构上的差异,只是按照功能和目地分类:

  • 框架模块 :这些是框架的核心模块,像缓存、邮件、主题、安全性、序列化、验证、Ef Core集成、MongoDB集成...等等。它们没有应用程序/业务功能,但通过提供通用基础架构,集成和抽象会使你的日常开发更加容易。

  • 应用程序模块 :这些模块是实现特定的应用程序/业务功能,像 博客、文档管理、身份管理、租户管理... 等等。它是通常有自己的实体,服务,API和UI组件。

怎么使用模块?

Abp vNext  框架中这些模块怎么像积木一样互相拼装呢?

模块之间的拼装只有三步:

  • 第一步:建立模块直接的依赖关系,可以通过  DependsOnAttribute  特性来确定依赖关系。

  • 第二步:先配置模块,实现为模块填充数据和功能设置。

  • 第三步:使用模块提供的功能(接口)。通过功能接口来实现模块拼装。

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<AppModule>(); //配置启动的 Abp模块
}
public void Configure(IApplicationBuilder app)
{
app.InitializeApplication(); //初始化 Abp模块
}
}

怎么自定义模块?

Abp vNext  规定每个模块都应该定义一个模块类并且继承  AbpModule  抽象类。

  • 通过  DependsOnAttribute  特性来关联需要使用的模块。

  • 通过重写  OnApplicationInitialization 方法来初始化模块。也可以配置  AspNetCore  处理管道。

  • 通过重写  ConfigureServices  方法来配置模块。

[DependsOn(typeof(ModuleThree.ModuleThreeModule))]
[DependsOn(typeof(ModuleOne.ModuleOneModule))]
[DependsOn(typeof(AbpAspNetCoreMvcModule))]
public class AppModule : AbpModule
{


public override void ConfigureServices(ServiceConfigurationContext context)
{
// 配置依赖注入
}


public override void
OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
app.UseStaticFiles();
app.UseRouting();
app.UseConfiguredEndpoints();
}
}

AbpModule 深度剖析

ABP 系统在启动的时候才会通过反射扫描所有模块,每个模块可以通过  DependsOnAttribute  特性来确定依赖关系,使用拓扑排序算法,来根据依赖性确定模块的加载顺序。(从最深层的模块依次加载,直到启动所有模块)。

AbpModule  的提供一些方法来管理模块的生命周期。

  • ConfigureServices :是将你的服务添加到依赖注入系统并配置其他模块的主要方法。

  • OnApplicationInitialization :初始化配置的所有模块的所有服务。

  • OnApplicationShutdown :如果要在应用程序关闭时执行。

  • ... 还有其他方法用的不多,下面流程图会有简单说明。

下面这个流程图简单阐述  AbpModule  提供的方法之间的执行顺序。

aaUVf2U.png!mobile

AbpModule  类源代码:

https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModule.cs

举一个定时发邮件例子来说明这三个方法用处。

  • 自定义了一个定时发邮件模块  SendMailModule  模块并且继承  AbpModule  。

  • 在  ConfigureServices  方法中配置定时发送的时间和发送邮箱的地址,邮件模块信息等。

  • 配置好模块之后,在  OnApplicationInitialization 方法中启动定时器,进行定时发送邮件。

  • 当系统停止后需要提醒运维人员,在  OnApplicationShutdown  方法中发送一封邮件给运维人员。

ABP 模块化依赖价值流程

bEZn22.png!mobile

下面日志阐述 AbpModule  提供的方法在有模块依赖的情况下之间的执行顺序。

RfuYvqf.png!mobile

上图的执行顺序的演示代码:

AbpModuleDemo.7z

总结

Abp vNext  是一个模块化设计,提供了高扩展性、高可用性、高效率开发框架。要实现高效率前提还需要熟练了解使用 Abp 中的所有模块功能。通过模块设计也可以很快定制一下功能以及更好的单元测试。

Abp vNext  模块设计是直接采用  Asp.NetCore  的原有功能,扩展了  Startup.ConfigureServices  和  Startup.Configure  方法,把方便我们在开发模块的时候直接使用  IServiceCollection  和  IApplicationBuilder

模块设计原则

  • 单一原则。每个模块只有一个功能,有着清晰的边界,实现高度解耦和高度可复用性。

  • DDD领域设计。通过领域设计思想确定模块的领域边界,避免模块化过于细化导致增加复杂程度。

模块使用常见问题

  • 模块化过于细化,很容易陷入模块的迷宫中。导致学习成本暴增。

  • 模块功能文档不清晰,使用起来问题频出。

  • 模块之间的过于依赖,对模块设计和功能不了解时,很难定位问题。

引用

  • Abp vNext 源码分析

    https://www.cnblogs.com/myzony/p/10722506.html

  • 官方文档

    https://docs.abp.io/zh-Hans/abp/latest/Module-Development-Basics

bEZn22.png!mobile

转载是一种动力 分享是一种美德

6FraeqB.gif!mobile

作者: 阿凌

【版权声明】作品来自于长沙.NET技术社区成员【阿凌】,有兴趣了解长沙.NET技术社区详情,请关注公众号【DotNET技术圈】,作品版权归作者和博客园共有,作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

QQ群:

编程交流群<85318032>

产品交流群<897857351>

vIRbeuf.png!mobile

FNZvumm.jpg!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK