• ABP - 模块加载机制


    Abp是一个基于模块化开发的应用程序框架,提供了模块化基础的架构和模块化加载的引擎。

    理解模块

    一个模块是对一个功能点的封装,可以独立成为一个包,实现了松耦合的代码组织方式。Abp框架的基本思想就是模块开发,模块就想乐高中的一块块积木,在项目中将不同功能点的模块引用进来,就像搭积木一样构建成一个成品。

    模块化的实现

    通过在一个程序集中,创建一个模块类,继承AbpModule类,就可以很简单的将这个程序集作为Abp框架中的一个模块。如下面的代码,就是一个模块类的定义。

    [DependsOn(
    	typeof(AbpAutoMapperModule),
    	typeof(AbpDddApplicationModule),
    	typeof(AbpObjectExtendingModule)
    	)]
    public class BaseApplicationModule : AbpModule
    {
    	public override void ConfigureServices(ServiceConfigurationContext context)
    	{
    		Configure(options =>
    		{
    			options.AddMaps();
    		});
    	}
    
    	public override void OnApplicationInitialization(ApplicationInitializationContext context)
    	{
    		base.OnApplicationInitialization(context);
    	}
    }
    

    AbpModule是 abp框架的模块基础类,一个类库可以通过一个继承此类的类,声明为一个模块。通过对AbpModule类的查看,可以看到这是一个抽象类,它很好的遵循了接口隔离原则。

    image

    一个模块就是一个完整的功能点,往往需要对其依赖的一些东西进行配置,如数据库连接、如配置文件读取等。Abp引擎通过将.net Core管道和容器传递,使得模块中可以配置自己的依赖注入和请求管道,而不需要在外部使用的时候添加一大堆配置,这样就达到了独立开放,开箱即用的目的。

    通过重写PreConfigureServicesConfigureServicesPostConfigureServices这三个方法,可以在模块内部完成该模块的依赖注入配置。通过重写OnPreApplicationInitializationOnApplicationInitializationOnPostApplicationInitializationOnApplicationShutdown这四个方法可完成模块在应用程序生命周期中的配置,在应用程序启动或者停止的时候做一些操作,也可以对asp.net Core的请求管道进行操作,例如加入自己的中间件。这些方法大家也并不陌生,和Asp.net Core中Startup类中的方法类似。

    模块之间可以引用,并且设置模块的依赖关系,一个模块加载时,会先加载其依赖的模块。通过DependsOnAttribute可以指定模块依赖的模块,形成一个依赖链,Abp引擎启动时加载模块时,会先加载依赖模块。

    Volo.Abp.Core 核心包

    Volo.Abp.Core是Abp框架的核心包,关于Abp模块化的实现都在这个包中,我们可以通过对这个包的源码的研究,看下Abp模块化的实现方式。

    首先,从Volo.Abp.Core的源码中,可以看到这个包也依赖于一些第三方包。

    image

    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框架中来处理。

    image

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

    image

    image

    AbpApplicationFactory: abp应用启动的基本方式,是整个程序的入口,也是研究模加载机制的入口。根据使用的依赖注入容器的不同,提供两类的Create方法的重载。

    应用程序引擎(容器)初始化时,通过应用程序引擎IAbpAppliaction,即AbpApplicationWithExternalServiceProvider,拿到各个模块信息(通过模块描述),执行各个模块中配置好的依赖注入。

    而通过InitializeApplication(this IApplicationBuilder app)方法,可以看到也是通过容器拿到驱动,即AbpApplicationWithExternalServiceProvider示例,然后调用了Initialize(IServiceProvider serviceProvider)方法。

    image

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

    image

    abp应用程序初始化过程图

    image

    以上,就是对Abp应用程序启动和模块加载机制的整理.

    除此之外,volo.abp.core类库中还提供了一些工具类和扩展方法,都是很好用的,就算不用abp框架的童鞋也可以借鉴其中的写法,或者直接拿到自己项目中使用。

    有兴趣的童鞋可以自己再仔细查看一下源码。



    ABP 系列总结:

    目录:ABP 系列总结
    上一篇:ABP - 初识 ABP
    下一篇:ABP - 依赖注入(1)

  • 相关阅读:
    k8s搭建EFK日志系统
    少数据量情况下的深度学习模型训练效果提升技巧
    说说你对slot的理解?
    接口与抽象类的区别
    React + TypeScript + Taro前端开发小结
    LeetCode(力扣)62. 不同路径Python
    MIT 6.s081操作系统实验 Lab2: system calls
    DotNetGuide荣登GitHub C#中文 Trending 月榜第一
    不可不知的4个搜索技巧——你真的会“百度一下”么?
    jna调用dll文件正常,但是怎么样初始化.ini文件,总是提示未找到.ini文件?
  • 原文地址:https://www.cnblogs.com/wewant/p/17125189.html