【ABP框架系列学习】模块系统(4)
0.引言
ABP提供了构建模块和通过组合模块以创建应用程序的基础设施。一个模块可以依赖于另外一个模块。通常,程序集可以认为是模块。如果创建多个程序集的应用程序,建议为每个程序集创建模块定义。
当前,模块系统主要集中在服务器,而不是客户端。
1.模块定义
模块是从ABP包中的AbpModule派生的类定义的。比如说开发一个可以用于不同应用程序的博客模块(Blog Module)。最简单的模块定义如下 :
- public class MyBlogApplicationModule : AbpModule
- {
- public override void Initialize()
- {
- IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
- }
- }
模块定义类负责通过依赖注入注册类,如有必要(可以像上述事例按惯例完成)。它还可以配置应用程序和其它模块,给应用程序增加新的功能等等。
2.生命周期方法
ABP在程序启动和关闭时调用模块一些特定的方法。你可以重写这些方法以执行某些特定的任务。
ABP按照依赖顺序调用这些方法。如果模块A依赖模块B,那么模块B在模块A之前初始化。
启动方法执行准确的顺序:PreInitialize-B, PreInitialize-A, Initialize-B, Initialize-A, PostInitialize-B, PostInitialize-A。对于所有依赖关系图都是如此。关闭方法也是类似的,但顺序相反。
相关源码:模块启动时依次执行PreInitialize()、Initialize()、PostInitialize(),模块关闭时首先Reverse()、然后在逐个模块Shutdown()。
- public virtual void StartModules()
- {
- var sortedModules = _modules.GetSortedModuleListByDependency();
- sortedModules.ForEach(module => module.Instance.PreInitialize());
- sortedModules.ForEach(module => module.Instance.Initialize());
- sortedModules.ForEach(module => module.Instance.PostInitialize());
- }
- public virtual void ShutdownModules()
- {
- Logger.Debug("Shutting down has been started");
- var sortedModules = _modules.GetSortedModuleListByDependency();
- sortedModules.Reverse();
- sortedModules.ForEach(sm => sm.Instance.Shutdown());
- Logger.Debug("Shutting down completed.");
- }
PreInitialize
当应用程序启动时,首先调用该方法。它是框架和其它模块初始化之前配置它们的首选方法。
你还可以在该方法中编写特定的代码,以便在依赖注入注册之前运行。例如,如果你创建一个传统的注册类,那么你应在该方法中使用IOCManager.AddConventionalRegisterer方法注册它们。
Initialize
该方法是依赖注入注册的地方,通过使用IocManager.RegisterAssemblyByConvention方法完成注册。如果想定义自定义的依赖注册,请见后续依赖注入章节。
PostInitialize
该方法在程序启动的最后调用。在这里解析依赖是安全的。
Shutdown
该方法在程序关闭时调用。
3.模块依赖(Module Dependencies)
一个模块可以依赖于另外的模块。你可以通过DependsOn特性显示声明依赖项,如下代码:
- [DependsOn(typeof(MyBlogCoreModule))]
- public class MyBlogApplicationModule : AbpModule
- {
- public override void Initialize()
- {
- IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
- }
- }
上述事例代码中,声明了MyBlogApplicationModule模块依赖于MyBlogCoreModule模块,那么MyBlogCoreModule模块应该在MyBlogApplicationModule模块之前完成初始化。
ABP可以从启动模块(start module)开始就递归的解析依赖关系,并相应地初始化它们。启动模块(start module)是最后进行初始化的模块。
4.插件模块
虽然模块从启动模块开始查找并遍历依赖关系,ABP还可以动态加载模块。AbpBootstrapper类中定义了PlugInSources属性,该属性可用于向动态加载的插件模块添加源。插件源可以是实现IPlugInSource接口的任何类。通过实现FolderPlugInSource类以从指定文件夹中的程序集获取插件模块。
ASP.NET CORE
ABP中ASP.NET CORE模块在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 in PlugIns
如果你的模块包括MVC或Web API Controolers,ASP.NET不能查找你的控制器。为了克服这个问题,你可以修改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();
- }
- }
- }
附加程序集(Additional Assemblies)
默认实现IAssemblyFinder和ITypeFinder接口只能在这些程序集中查找模块程序集和类型。也可以在模块中重写GetAdditionalAssembliesy方法来包括其它程序集。
自定义模块方法(Custom Module Methods)
你的模块还可以拥有自定义的方法,并能在依赖于这个模块的其它模块中调用这个方法。假设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。
模块配置(Module Configuration)
然而自定义方法可以用来配置模块,建议使用启动配置(startup configuration)系统来定义和设置模块的配置。
模块生命周期(Module Lifetime)
模块类自动注册为单实例对象(singleton)。
【ABP框架系列学习】模块系统(4)的更多相关文章
- [ABP]浅谈模块系统与 ABP 框架初始化
在 ABP 框架当中所有库以及项目都是以模块的形式存在,所有模块都是继承自AbpModule 这个抽象基类,每个模块都拥有四个生命周期.分别是: PreInitialze(); Initialize( ...
- 【ABP框架系列学习】启动配置(5)
ABP提供了在启动时配置模块的基础设施和模型. 1.配置ABP 配置ABP是在模块的PreInitialize方法中完成的,例如: public class SimpleTaskSystemModul ...
- 【ABP框架系列学习】介绍篇(1)
0.引言 该系列博文主要在[官方文档]及[tkbSimplest]ABP框架理论研究系列博文的基础上进行总结的,或许大家会质问,别人都已经翻译过了,这不是多此一举吗?原因如下: 1.[tkbSim ...
- 【ABP框架系列学习】模块系统(4)之插件示例开发
0.引言 上一篇博文主要介绍了ABP模块及插件的相关知识,本章节主要开发一个插件示例来学习如何创建一个插件,并在应用程序中使用.这个命名为FirstABPPlugin的插件主要在指定的时间段内删除审计 ...
- ABP理论学习之模块系统
返回总目录 本篇目录 模块介绍 生命周期事件 模块依赖 自定义模块方法 模块介绍 ABP提供了构建模块并将这些模块组合起来创建应用的基础设施.一个模块可以依赖另一个模块.一般来说,一个程序集可以认为是 ...
- 【ABP框架系列学习】N层架构(3)
目录 0.引言 1.DDD分层 2.ABP应用构架模型 客户端应用程序(Client Applications) 表现层(Presentation Layer) 分布式服务层(Distributed ...
- abp框架(aspnetboilerplate)扩展系统表
以OrganizationUnit为例,进行扩展,加入IsUse属性 1.创建一个新类,比如ExtendedOrganizationUnit,继承OrganizationUnit public cla ...
- [Abp vNext 源码分析] - 2. 模块系统的变化
一.简要说明 本篇文章主要分析 Abp vNext 当中的模块系统,从类型构造层面上来看,Abp vNext 当中不再只是单纯的通过 AbpModuleManager 来管理其他的模块,它现在则是 I ...
- abp 模块系统
abp模块系统:ABP理论学习之模块系统 ABP提供了构建模块并将这些模块组合起来创建应用的基础设施.一个模块可以依赖另一个模块.一般来说,一个程序集可以认为是一个模块.一个模块是由一个派生了AbpM ...
随机推荐
- 旅游类App的原型制作分享-Klook
Klook是一款旅游类App,它能探索和预订惊人的旅行活动.在世界各地以最优惠的价格畅玩. 这款原型中,用到了Mockplus的两种滚动方式,一种是把手机外壳拉长,另一种是使用滚动区组件,其中,滚动区 ...
- 关于mysql存储过程中传decimal值会自动四舍五入的这个坑
容我说几句题外话:我的工作日常是用微软系的,SQL SERVICE 存储过程很强大,我也很习惯很喜欢用存储过程.和MySQL结缘,是在五年前,因为一些原因,公司要求用开源免费的数据库.很多时候,用my ...
- nginx 配置文件学习
######Nginx配置文件nginx.conf中文详解##### #定义Nginx运行的用户和用户组 user www www; #nginx进程数,建议设置为等于CPU总核心数. worker_ ...
- C# BitArray 二进制处理
int k = 6; byte[] bytearr = BitConverter.GetBytes(k); BitArray myBA = new BitArray(bytearr); for (in ...
- DNN原理探究系列之目录与序章篇
序言: 神经网络结构,作为最成功的机器学习模型之一,其工作原理一直被埋藏得比较深,其解释性以至于被称为黑盒. 自己对于DNN的理解也只能算刚踏入了门槛,对于人脑的原理与DNN原理之间的互通性,一直是非 ...
- spring boot 注解
一级注解:(写在类名前面的)@RestController: 等价于在函数前面写@ResponseBody ,会直接返回要显示的内容 @ControllerString返回的是模板文件的名称. 二级注 ...
- eclipse中修改maven本地仓库方式
1.安装maven,教程可参考:https://jingyan.baidu.com/article/4f7d5712a1306c1a21192746.html 2.安装成功后,可以打开eclipse新 ...
- CoUninitialize引发的一个错误
程序开始已使用CoUninitialize,后边的函数又再次调用CoUninitialize,判断返回值,导致函数提前退出返回异常.
- Linux学习---类型修饰符
auto eg:aoto int a; 默认情况--------->分配的内存可读可写的区域. register eg:register int a; 限制变量定义在寄存器上的修饰符 定义一 ...
- Maths | 病态问题和条件数
目录 1. 概念定义 1.1. 病态/ 良态问题 1.2. 适定/ 非适定问题 1.3. 良态/ 病态矩阵和条件数 2. 病态的根源 3. 计算条件数的方法 3.1. 与特征值的关系 3.2. 与奇异 ...