AbpVnext 框架解读系列(一)| 模块化

2,738 阅读3分钟

谁适合阅读本文 ❓

  • 想使用ABP框架进行开发的同学⭐
  • 对ABP框架感兴趣的同学⭐
  • 已经使用了ABP框架开发,想了解其中的一些原理或者设计⭐
  • 一起学习新知识⭐

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

前言

使用过的同学应该都知道,ABP是一个模块一个单独的解决方案,整个模块的设计都遵循了领域驱动设计!每个模块都应该定义一个模块类,定义模块类的最简单方法是创建一个派生自AbpModule,ABP的整个分层模块如下图!

image.png

AbpModule详解

为什么要设计成模块化,使用模块化又能为系统带来什么?模块化作为ABP框架的核心,它是怎么实现的?

模块化的意义

  • 模块化开发的意义我觉得在于高内聚,低耦合,模块与模块之间相互独立,但又可以自由组合,能使系统灵活性非常强,提高了代码的可维护性,复用性。

ABP模块化详解

模块的初始化动作是在 AbpApplicationBase 基类开始的,源码地址。主要是注入模块相关的基础设施,还包括了LoadModules()方法,以及遍历所有模块,并按照预加载、初始化、初始化完成的顺序执行其生命周期方法

image.png

protected virtual IReadOnlyList<IAbpModuleDescriptor> LoadModules(IServiceCollection services, AbpApplicationCreationOptions options)
{
    return services
        .GetSingletonInstance<IModuleLoader>()
        .LoadModules(
            services,
            StartupModuleType,
            options.PlugInSources
        );
}
  • 模块的初始化在IModuleLoader 的默认实现 ModuleLoader 主要做了哪些事情呢?
    • 参数校验
    • 查找所有的模块类型,并创建模块描述。主要是通过AbpModuleHelper.FindAllModuleTypes()方法
    • 解析依赖关系,对列表进行拓扑排序。

image.png

image.png

  • 执行完上述操作之后我们可以看到AbpApplicationBase类的最后一个操作执行模块的三个生命周期方法,源码地址
if (!options.SkipConfigureServices)
{
    ConfigureServices();//执行模块的三个生命周期方法
}
  • AbpModule提供一些方法来管理模块的生命周期
    • ConfigureServices将你的服务添加到依赖注入系统并配置其他模块的主要方法
    • OnApplicationInitialization初始化所有模块
    • OnApplicationShutdown应用关闭执行
    • . . . 还有一些如配置前后执行方法、初始化前后执行方法等等

模块的两种类型

  • 框架模块:如缓存, 邮件, 主题, 安全, 序列化, 验证... 等. 它们没有应用/业务功能,它们提供了日常开发经常用到的通用基础设施,集成和抽象.
  • 应用程序模块: 这些模块实现了 特定的应用/业务功能 像博客, 文档管理, 身份管理, 租户管理... 等等. 它们通常有自己的实体,服务,API和UI组件. 请参阅 预构建的应用程序模块.

如何使用自定义模块

既然我们上文中提到,模块之间可以灵活组合配置,那么我们在应用程序中如何使用呢?
只需要声明 [DependsOn] 特性,ABP在启动时会调查应用程序的依赖关系,并以正确的顺序初始化/关闭模块

image.png

总结

第一次读ABP源码,读了好几天,也看了不少文章,但是总感觉有一些似懂非懂的感觉。本文如果有一些补充不够的可以指出来,我会虚心学习。
Abp vNext的模块化设计,提供了高扩展性、高可用性、高效率开发框架。要实现高效率前提还需要熟练了解使用 Abp中的所有模块功能。