ABP - 模块加载机制
Abp是一个基于模块化开发的应用程序框架,提供了模块化基础的架构和模块化加载的引擎。
理解模块
一个模块是对一个功能点的封装,可以独立成为一个包,实现了松耦合的代码组织方式。Abp框架的基本思想就是模块开发,模块就想乐高中的一块块积木,在项目中将不同功能点的模块引用进来,就像搭积木一样构建成一个成品。
模块化的实现
通过在一个程序集中,创建一个模块类,继承AbpModule类,就可以很简单的将这个程序集作为Abp框架中的一个模块。如下面的代码,就是一个模块类的定义。
[DependsOn(
typeof(AbpAutoMapperModule),
typeof(AbpDddApplicationModule),
typeof(AbpObjectExtendingModule)
)]
public class BaseApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<BaseApplicationModule>();
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
base.OnApplicationInitialization(context);
}
}
AbpModule是 abp框架的模块基础类,一个类库可以通过一个继承此类的类,声明为一个模块。通过对AbpModule类的查看,可以看到这是一个抽象类,它很好的遵循了接口隔离原则。

一个模块就是一个完整的功能点,往往需要对其依赖的一些东西进行配置,如数据库连接、如配置文件读取等。Abp引擎通过将.net Core管道和容器传递,使得模块中可以配置自己的依赖注入和请求管道,而不需要在外部使用的时候添加一大堆配置,这样就达到了独立开放,开箱即用的目的。
通过重写PreConfigureServices、ConfigureServices、PostConfigureServices这三个方法,可以在模块内部完成该模块的依赖注入配置。通过重写OnPreApplicationInitialization、OnApplicationInitialization、OnPostApplicationInitialization、OnApplicationShutdown这四个方法可完成模块在应用程序生命周期中的配置,在应用程序启动或者停止的时候做一些操作,也可以对asp.net Core的请求管道进行操作,例如加入自己的中间件。这些方法大家也并不陌生,和Asp.net Core中Startup类中的方法类似。
模块之间可以引用,并且设置模块的依赖关系,一个模块加载时,会先加载其依赖的模块。通过DependsOnAttribute可以指定模块依赖的模块,形成一个依赖链,Abp引擎启动时加载模块时,会先加载依赖模块。
Volo.Abp.Core 核心包
Volo.Abp.Core是Abp框架的核心包,关于Abp模块化的实现都在这个包中,我们可以通过对这个包的源码的研究,看下Abp模块化的实现方式。
首先,从Volo.Abp.Core的源码中,可以看到这个包也依赖于一些第三方包。

Fody: 可以在编译过程中拦截vs行为,动态地将一些代码添加到dll中,实现静态AOP的功能。
JetBrains: 提供一些数据标识,可以在编译期间对参数进行检查,减少bug
Nito:能够在使用Lock排他锁的时候,使用await异步的方式
SoureLink:支持在安装nuget包之后,动态地从git中下载源码以供调试,需要在vs中设置启用源程序调试
System.Collection.Immutable: 不可变集合,不可以往集合add
System.Linq.Dynamic.Core:动态linq,将强类型的Linq表达式变成字符串的方式进行操作
模块加载过程
ABP框架的启动过程,最根本的就是模块的装载过程。
众所周知,asp.net core程序的启动类时startup类,而在abp框架中,startup类却很简单,虽然代码简单,但是这两个方法却不简单,正是通过这两个方法,将asp.net core中的请求转移到abp框架中来处理。

以AddApplication<TStartupModule>()扩展方法作为入口,通过查看源码,可以看到内部是通过AbpApplicationFactory创建了一个abp应用程序的驱动AbpApplicationWithExternalServiceProvider,在这个驱动类中完成了对abp框架启动的配置和操作。


AbpApplicationFactory: abp应用启动的基本方式,是整个程序的入口,也是研究模加载机制的入口。根据使用的依赖注入容器的不同,提供两类的Create方法的重载。
应用程序引擎(容器)初始化时,通过应用程序引擎IAbpAppliaction,即AbpApplicationWithExternalServiceProvider,拿到各个模块信息(通过模块描述),执行各个模块中配置好的依赖注入。
而通过InitializeApplication(this IApplicationBuilder app)方法,可以看到也是通过容器拿到驱动,即AbpApplicationWithExternalServiceProvider示例,然后调用了Initialize(IServiceProvider serviceProvider)方法。

ABP框架应用程序启动,模块加载整个过程涉及到了AbpApplicationFactory、AbpApplicationWithExternalServiceProvider、AbpApplicationBase、IModuleLoader、IModuleManager等类和接口,这里不好把这些源码都列出来,所以就整理了一下简单的流程和调用关系。见下图。

abp应用程序初始化过程图

以上,就是对Abp应用程序启动和模块加载机制的整理.
除此之外,volo.abp.core类库中还提供了一些工具类和扩展方法,都是很好用的,就算不用abp框架的童鞋也可以借鉴其中的写法,或者直接拿到自己项目中使用。
有兴趣的童鞋可以自己再仔细查看一下源码。
ABP 系列总结:
目录:ABP 系列总结
上一篇:ABP - 初识 ABP
ABP - 模块加载机制的更多相关文章
- 【前端】CommonJS的模块加载机制
CommonJS的模块加载机制 CommonJS模块的加载机制是,输入的是被输出的值的拷贝.也就是说,一旦输出一个值,模块内部的变化就影响不到这个值. 例如: // lib.js var counte ...
- Dojo初探之1:AMD规范,编写符合AMD规范(异步模块加载机制)的模块化JS(其中dojo采用1.11.2版本)
一.AMD规范探索 1.AMD规范(即异步模块加载机制) 我们在接触js的时候,一般都是通过各种function来定义一些方法,让它们帮我们做一些事情,一个js可以包含很多个js,而这些functio ...
- nodejs(13)模块加载机制
模块加载机制 优先从缓存中加载 当一个模块初次被 require 的时候,会执行模块中的代码,当第二次加载相同模块的时候,会优先从缓存中查找,看有没有这样的一个模块! 好处:提高模块的加载速度:不需要 ...
- Skywalking-13:Skywalking模块加载机制
模块加载机制 基本概述 Module 是 Skywalking 在 OAP 提供的一种管理功能特性的机制.通过 Module 机制,可以方便的定义模块,并且可以提供多种实现,在配置文件中任意选择实现. ...
- nodejs之模块加载机制
nodejs模块加载原理 node加载模块步骤: 1) 路径分析 (如判断是不是核心模块.是绝对路径还是相对路径等) 2) 文件定位 (文件扩展名分析, 目录和包处理等细节) 3) 编译执行 原生模块 ...
- Node.js中模块加载机制
1.模块查找规则-当模块拥有路径但没有后缀时:(require(‘./find’)) require方法根据模块路径查找模块,如果是完整路径,直接引入模块: 如果模块后缀省略,先找同名JS文件,再找同 ...
- node模块加载机制。
- javascript 异步模块加载 简易实现
在javascript是没有类似java或其他语言的模块概念的,因此也不可能通过import或using等关键字来引用模块,这样造成了复杂项目中前端代码混乱,变量互相影响等. 因此在复杂项目中引入AM ...
- 也谈模块加载,吐槽CMD
先吐槽CMD,不要没头没脑的搞出个CMD,没意思. 大家都看AMD好了,异步模块加载机制,CMD并没有改变这个模式. 模块加载的关口就是getCurrentScript,每次define被调用的时候, ...
- 基于python的opcode优化和模块按需加载机制研究(学习与个人思路)(原创)
基于python的opcode优化和模块按需加载机制研究(学习与思考) 姓名:XXX 学校信息:XXX 主用编程语言:python3.5 个人技术博客:http://www.cnblogs.com/M ...
随机推荐
- docker搭建consul集群
防止自己忘了,做个笔记. 环境为两台主机,ip分别为: 192.168.2.9,192.168.2.7 首先在 192.168.2.9 上执行一下命令: docker run -d --name ...
- 宏任务&微处理
事件循环 JavaScript 语言的一大特点就是单线程,同一个时间只能做一件事.为了协调事件.用户交互.脚本.UI 渲染和网络处理等行为,防止主线程的不阻塞,Event Loop 的方案应用而生. ...
- SpringBoot部署到外部Tomcat无法注册到Nacos服务端
事情经过 近期做一个项目投标演示(POC)环境支持,需要集成Nacos服务端.考虑到现有项目中已经有了Nacos相关依赖,那还不简单?新建个服务端,配置几下重启不就搞定了吗?然而事情远没有想得这么简单 ...
- Javacv 音视频小工具 - 下载抖音视频
一.前言 大家好,俗话说的好,学习新的知识后要学以致用,在学习音视频的过程中,你有没有疑问,不知道音视频可以用来做什么.下面举几个例子,比较耳熟能详,被吹到风口的一些场景有:AI 视觉计算, AI 人 ...
- Linux Bash Shell 中变量的 5 个易错点
Linux 中的 Bash 脚本支持对变量的操作,下面咸鱼将介绍 Linux Bash Shell 中关于变量的 5 个易错点 因为编程习惯,这类现象往往发生在大多数使用过其他流行编程语言的程序员身上 ...
- uniapp中easycom用法详解
Uniapp中的easycom是一种组件自动注册机制,可以让开发者更加方便地使用和管理组件.下面详细介绍下关于easycom使用方法. 什么是easycom? easycom是Uniapp框架提供的一 ...
- 改善与提高linux系统的音质
当初装Linux系统的时候,我就发现了,deepin和ubuntu的linux平台音质和Windows平台下的音质不一样.硬件参数没变,歌曲音频文件相同的情况下,linux播放歌曲的时候动态和音乐细节 ...
- 探究平台化设计的核心思想和Lattice的设计原则
一. 平台对业务敏捷支撑的挑战 早期阿里的交易中台遇到了一些挑战,这个在毗卢的博客中有提到,主要遇到了这些问题:新小业务都有一个成长规律,在早期业务模式验证阶段,需要的玩法比较简单,希望能频繁的发布快 ...
- 机器学习算法(九): 基于线性判别模型的LDA手写数字分类识别
1.机器学习算法(九): 基于线性判别模型的LDA手写数字分类识别 1.1 LDA算法简介和应用 线性判别模型(LDA)在模式识别领域(比如人脸识别等图形图像识别领域)中有非常广泛的应用.LDA是一种 ...
- Linux 磁盘空间查看及清理
1. 查看磁盘空间 查看当前目录各文件夹大小 du -ah -x --max-depth=1 查看文件大小 ls -lh 查看系统空间占用 df -h 2. 磁盘空间清理 Linux清除文件内容 ca ...