一、概述
Abp
本身是一个包含许多 nuget
包的模块化框架。它还提供了一个完整的基础架构来开发你自己的具有实体、服务、数据库集成、AP、UI 组件等等功能的应用程序模块。
每个模块都应该定义一个模块类。模块类指实现了 IAbpModule
接口的非抽象非泛型类。定义模块类的最简单方法是创建一个派生自 AbpModule
的类,AbpModule 是一个实现了 AbpModule 接口的抽象非泛型类。
二、IAbpModule
1 | // File: src\Volo.Abp.Core\Volo\Abp\Modularity\IAbpModule.cs |
1 | // File: src\Volo.Abp.Core\Volo\Abp\Modularity\ServiceConfigurationContext.cs |
ServiceConfigurationContext
类比较简单,就 2 个属性。在加载模块时会为每个模块类创建一个 ServiceConfigurationContext 实例并调用其 ConfigureServices
方法。
三、AbpModule
该部分内容主要来自官方文档。
1、ConfigureServices
实现自 IAbpModule
接口的方法。
1 | // File: src\Volo.Abp.Core\Volo\Abp\Modularity\AbpModule.cs |
2、配置服务前和后
AbpModule 类还定义了 PreConfigureServices
和 PostConfigureServices
方法用来在 ConfigureServices
之前或之后覆盖和编写你的代码。请注意,在这些方法中编写的代码将在所有其他模块的 ConfigureServices
方法之前/之后执行。
1 | public virtual void PreConfigureServices(ServiceConfigurationContext context) |
3、应用程序初始化
一旦配置了所有模块的所有服务,应用程序就会通过初始化所有模块来启动。在此阶段,你可以从 IServiceProvider
中获取服务,因为这时它已准备就绪且可用.
可以在启动应用程序时覆盖 OnApplicationInitialization
方法来执行代码。
1 | public virtual void OnApplicationInitialization(ApplicationInitializationContext context) |
4、应用程序初始化前和后
AbpModule 类还定义了 OnPreApplicationInitialization
和 OnPostApplicationInitialization
方法用来在 OnApplicationInitialization 之前或之后覆盖和编写你的代码。请注意,在这些方法中编写的代码将在所有其他模块的 OnApplicationInitialization 方法之前/之后执行。
1 | public virtual void OnPreApplicationInitialization(ApplicationInitializationContext context) |
5、应用程序关闭
最后,如果要在应用程序关闭时执行某些代码,你可以覆盖 OnApplicationShutdown
方法。
1 | public virtual void OnApplicationShutdown(ApplicationShutdownContext context) |
6、模块依赖
在模块化应用程序中,一个模块依赖于另一个或几个模块并不罕见.如果一个 Abp 模块依赖于另一个模块,它必须声明 DependsOnAttribute
特性。
四、AbpModuleDescriptor
AbpModuleDescriptor 包含的模块的类型、所在程序集合、实例、是否以插件形式加载和依赖的其他模块。
1 | // File: src\Volo.Abp.Core\Volo\Abp\Modularity\AbpModuleDescriptor.cs |
五、ModuleLoader
ModuleLoader
的核心方法是 LoadModules
方法,该方法主要进行如下操作:
1、获取模块描述符
从启动模块(StartupModule)开始递归查找所有依赖的模块类型。并根据模块类型创建 模块描述符
(Module Descriptor)。在此过程中会创建模块实例,实例会以单例服务形式注入到 IoC 中,也会存入模块描述符中。基于模块描述符集合,再设置各个模块描述符所以依赖的其他模块描述符(AbpModuleDescriptor
的 IReadOnlyList<IAbpModuleDescriptor> Dependencies
)。
使用 AbpModuleHelper.FindAllModuleTypes
查找模块类型,其根据标注在模块类定义之上的 DependsOnAttribute
(IDependedTypesProvider
) 所标注的类型进行递归查找。不会将同类型的模块类型重复收集。
创建模块类型实例是使用 Activator.CreateInstance(Type type)
方法,所以模块类型需提供无参构造函数(或无任何显示声明的构造函数)。
模块描述符的定义见 AbpModuleDescriptor 类。
2、模块排序
将模块集合进行拓扑排序,然后将启动模块置在集合的第一位。
3、注册模块服务
首先针对实现了 IPreConfigureServices
接口的模块,调用 PreConfigureServices
方法。然后针对继承自 AbpModule
的模块,如果 SkipAutoServiceRegistration
没有设置为 true(详见官方文档:依照约定的注册),将其所在程序集的某些服务进行自动注册。最后针对实现了 IPostConfigureServices
接口的模块,调用 PostConfigureServices
方法。
备注:
- AbpModule 实现了 IPreConfigureServices 和 IPostConfigureServices 接口。
- Conventional registrar 决定了哪些类会注册入 IoC。目前有 DefaultConventionalRegistrar、AbpAspNetCoreMvcConventionalRegistrar 和 AbpFluentValidationConventionalRegistrar。DefaultConventionalRegistrar 注册声明了 DependencyAttribute 特性和实现了接口 ITransientDependency、ISingletonDependency 或 IScopedDependency 接口的服务;AbpAspNetCoreMvcConventionalRegistrar 注册 PageModel、Controller 和 ViewComponent 。AbpFluentValidationConventionalRegistrar 注册
IValidator<T>
服务。
4、返回值
ModuleLoder 返回模块描述符数组。构造 AbpApplicationBase
实例会加载模块,即调用 LoadModules 方法,方法的返回值会赋给 AbpApplicationBase 的 Modules 属性
。
六、ModuleManager
ModuleManager
用于管理模块的生命周期。在应用程序初始化、应用程序初始化前和后以及应用程序关闭,分别调用各个模块的 OnApplicationInitialization、OnPreApplicationInitialization 和 OnPostApplicationInitialization 以及 OnApplicationShutdown 方法。
额外的,ModuleManager 能够以日志输出应用程序使用了哪些模块。