模块系统介绍
ABP 提供了基础设施功能来构建模块, 并通过组合这些模块来创建应用. 一个模块可以依赖于另一个模块. 一般来讲, 一个程序集被认为和定义成一个模块. 如果你的应用包含多个程序集, 那么你可以为每一个程序集都定义一个模块.
模块定义
ABP 中的一个模块是由继承于 AbpModule(AbpModule 定义在 ABP package 中)的一个类来定义的. 比如我们开发了一个博客模块, 可以被不同的应用程序使用, 那么一个最简单的博客模块定义如下:
- public class MyBlogApplicationModule : AbpModule
- {
- public override void Initialize()
- {
- IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
- }
- }
定义模块的类有一个职责就是通过依赖注入来注册模块中的类型, 如上代码所示:
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
当然, 除此之外, 它还可以配置应用程序, 实现新的功能等等
模块的生命周期
当应用程序启动和关闭时, ABP 会调用模块中的一组特定方法 PreInitialize,Initialize,PostInitialize,Shutdown. 你可以重写这些方法来执行特定任务.
ABP 是根据模块之间的依赖顺序来执行模块的这些方法的. 例如模块 A 依赖于模块 B, 那么模块 B 就会在模块 A 之前做初始化. 当应用程序启动时, 模块 A 和模块 B 中这些方法的执行顺序如下: PreInitialize-B-->PreInitialize-A-->Initialize-B-->Initialize-A-->PostInitialize-B-->PostInitialize-A
当应用程序关闭时, 过程与启动类似, 只是执行顺序与启动时是相反的.
PreInitialize
当启动时, 会首先调用 PreInitialize 方法, 它在模块初始化之前执行, 所以通常会将框架和模块的配置定义在这里. 同时, 一些在依赖注入之前执行的代码也会写在这里. 例如你定义一个传统的类, 那么你需要在这里调用 IocManager.AddConventionalRegisterer 方法来注册它.
Initialize
在 Initialize 方法中, 会通过依赖注入注册模块中定义的类型, 一般使用 IocManager.RegisterAssemblyByConvention 方法来来注册, 当然也可自定义类型注册.
PostInitialize
在启动过程中, 这是最后一个被调用的方法. 在这里可以安全的解析一个依赖.
Shutdown
在应用关闭时, 会调用此方法.
模块依赖
一个模块可以依赖于另一个模块, 你需要使用 DependsOn 特性来显示的定义模块间的依赖关系, 如下所示:
- [DependsOn(typeof(MyBlogCoreModule))]
- public class MyBlogApplicationModule : AbpModule
- {
- public override void Initialize()
- {
- IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
- }
- }
在这里, 我们定义 MyBlogApplicationModule 模块依赖于 MyBlogCoreModule 模块, 并且 MyBlogCoreModule 模块要在 MyBlogApplicationModule 模块之前进行初始化.
ABP 在启动模块中, 自动的解析模块之间的依赖关系并初始化模块. 启动模块是最后一个被初始化的模块.
插件模块
ABP 可以在启动模块中检测, 加载模块集, 也可以动态的加载模块, 这些动态加载的模块就称之为插件模块.
在动态加载模块时, 要指定插件模块的源, 在 AbpBootstrapper 类中定义了一个属性 PlugInSources, 就是用来指定插件模块的源. 任何一个实现了 IPlugInSource 接口的类都可以用来定义插件模块的源.
在 ABP 中提供了一个默认实现 PlugInFolderSource, 用于从指定的文件夹中获取插件模块.
ASP.NET CORE
在 ABP ASP.NET Core 模块的 Startup 类中, ABP 为 AddAbp 扩展方法定义了添加插件模块源的选项:
- services.AddAbp<MyStartupModule>(options =>
- {
- options.PlugInSources.Add(new FolderPlugInSource(@"C:\MyPlugIns"));
- });
也可以使用 AddFolder 扩展方法
- services.AddAbp<MyStartupModule>(options =>
- {
- options.PlugInSources.AddFolder(@"C:\MyPlugIns");
- });
ASP.NET MVC, web API
如果是 ASP.NET MVC 应用程序, 我们可以重写 global.asax 中的 Application_Start 方法来添加插件模块的源:
- public class MvcApplication : AbpWebApplication<MyStartupModule>
- {
- protected override void Application_Start(object sender, EventArgs e)
- {
- AbpBootstrapper.PlugInSources.AddFolder(@"C:\MyPlugIns");
- //...
- base.Application_Start(sender, e);
- }
- }
插件模块中的 Controllers
如果你在插件模块中定义了 MVC / Web API Controllers, ASP.NET 将不能检测到这些 Controllers, 要解决这个问题, 你需要修改 global.asax 代码文件如下:
- using System.Web;
- using Abp.PlugIns;
- using Abp.Web;
- using MyDemoApp.Web;
- [assembly: PreApplicationStartMethod(typeof(PreStarter), "Start")]
- namespace MyDemoApp.Web
- {
- public class MvcApplication : AbpWebApplication<MyStartupModule>
- {
- }
- public static class PreStarter
- {
- public static void Start()
- {
- //...
- MvcApplication.AbpBootstrapper.PlugInSources.AddFolder(@"C:\MyPlugIns\");
- MvcApplication.AbpBootstrapper.PlugInSources.AddToBuildManager();
- }
- }
- }
附加程序集
在 ABP 中定义了两个接口 IAssemblyFinder 和 ITypeFinder, 这两个接口是 ABP 用来检测应用中的程序中的程序集和类型的. ABP 为这两个接口提供了默认实现, 在默认实现中, 仅仅从上述模块 (通过启动模块定义的模块依赖解析出的模块, 以及插件模块) 中来查找程序集和类型. 如果想添加其他程序集, 可以重写 GetAdditionalAssemblies 方法.
模块中的自定义方法
在模块中可以定义自定义方法, 模块中的自定义方法可以被其他依赖的模块调用. 假设 MyModule2 模块依赖 MyModule1 模块, 并且想在 PreInitialize 方法中调用 MyModule1 模块的自定义方法, 如下代码所示:
- public class MyModule1 : AbpModule
- {
- public override void Initialize()
- {
- IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
- }
- public void MyModuleMethod1()
- {
- //this is a custom method of this module
- }
- }
- [DependsOn(typeof(MyModule1))]
- public class MyModule2 : AbpModule
- {
- private readonly MyModule1 _myModule1;
- public MyModule2(MyModule1 myModule1)
- {
- _myModule1 = myModule1;
- }
- public override void PreInitialize()
- {
- _myModule1.MyModuleMethod1(); //Call MyModule1's method
- }
- public override void Initialize()
- {
- IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
- }
- }
在这里, 我们通过构造函数注入将 MyModule1 模块注入到 MyModule2 模块, 这样我们就可以在 MyModule2 模块总调用 MyModule1 的方法了, 但是前提条件是 MyModule2 模块依赖 MyModule1 模块.
模块配置
ABP 中建议使用启动配置 (startup configuration) 来配置模块
模块生存期
定义模块的类会被自动注册为单例
来源: https://www.cnblogs.com/lcyhjx/p/8978010.html