Abp vNext 模块加载机制

abp,vnext,模块,加载,机制 · 浏览次数 : 46

小编点评

**生命周期** 生命周期是指应用程序从启动到关闭之间的所有阶段的活动。在创建和配置应用程序模块之前和之后,会执行相应的配置操作。 **PreConfigureServices** 在`ConfigureServices`方法中,执行了对模块的配置操作,例如设置配置上下文、加载模块等。 **ConfigureServices** 在`ConfigureServices`方法中,执行了对模块的配置操作,例如设置配置上下文、加载模块等。 **PostConfigureServices** 在`ConfigureServices`方法中,执行了对模块的配置操作,例如清理配置上下文、关闭资源等。 **OnPreApplicationInitialization** 在`OnPreApplicationInitialization`方法中,执行了对模块的配置操作,例如设置配置上下文、加载模块等。 **OnApplicationInitialization** 在`OnApplicationInitialization`方法中,执行了对模块的配置操作,例如设置配置上下文、加载模块等。 **OnPostApplicationInitialization** 在`OnPostApplicationInitialization`方法中,执行了对模块的配置操作,例如清理配置上下文、关闭资源等。 **OnApplicationShutdown** 在`OnApplicationShutdown`方法中,执行了对模块的配置操作,例如清理配置上下文、关闭资源等。

正文

文章目录

生命周期

  • PreConfigureServices 添加依赖注入或者其它配置之前
  • ConfigureServices 添加依赖注入或者其它配置
  • PostConfigureServices 添加依赖注入或者其它配置之后
  • OnPreApplicationInitialization 初始化所有模块之前
  • OnApplicationInitialization 初始化所有模块
  • OnPostApplicationInitialization 初始化所有模块之后
  • OnApplicationShutdown 应用关闭执行

OnPreApplicationInitializationOnPostApplicationInitialization方法用来在OnApplicationInitialization之前或之后覆盖和编写你的代码.请注意,在这些方法中编写的代码将在所有其他模块的OnApplicationInitialization方法之前/之后执行.

加载流程

  1. 进入到Startup
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddApplication<xxxManagementHttpApiHostModule>();
    }
}
  1. 查看AddApplication源码会调用AbpApplicationFactory.CreateAsync
public async static Task<IAbpApplicationWithExternalServiceProvider> CreateAsync(
    [NotNull] Type startupModuleType,
    [NotNull] IServiceCollection services,
    Action<AbpApplicationCreationOptions>? optionsAction = null)
{
    var app = new AbpApplicationWithExternalServiceProvider(startupModuleType, services, options =>
    {
        options.SkipConfigureServices = true;
        optionsAction?.Invoke(options);
    });
    await app.ConfigureServicesAsync();
    return app;
}
  1. 进入AbpApplicationWithExternalServiceProvider,我们可以看到继承AbpApplicationBase
internal class AbpApplicationWithExternalServiceProvider : AbpApplicationBase, IAbpApplicationWithExternalServiceProvider
{
    public AbpApplicationWithExternalServiceProvider(
        [NotNull] Type startupModuleType,
        [NotNull] IServiceCollection services,
        Action<AbpApplicationCreationOptions>? optionsAction
        ) : base(
            startupModuleType,
            services,
            optionsAction)
    {
        services.AddSingleton<IAbpApplicationWithExternalServiceProvider>(this);
    }

    void IAbpApplicationWithExternalServiceProvider.SetServiceProvider([NotNull] IServiceProvider serviceProvider)
    {
        Check.NotNull(serviceProvider, nameof(serviceProvider));

        // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
        if (ServiceProvider != null)
        {
            if (ServiceProvider != serviceProvider)
            {
                throw new AbpException("Service provider was already set before to another service provider instance.");
            }

            return;
        }

        SetServiceProvider(serviceProvider);
    }
  1. 查看AbpApplicationBase构造函数
 internal AbpApplicationBase(
        [NotNull] Type startupModuleType,
        [NotNull] IServiceCollection services,
        Action<AbpApplicationCreationOptions>? optionsAction)
    {
        services.AddCoreServices();
        services.AddCoreAbpServices(this, options);
        // 加载模块
        Modules = LoadModules(services, options);
    }
  1. 查看加载模块逻辑
public IAbpModuleDescriptor[] LoadModules(
    IServiceCollection services,
    Type startupModuleType,
    PlugInSourceList plugInSources)
{
    Check.NotNull(services, nameof(services));
    Check.NotNull(startupModuleType, nameof(startupModuleType));
    Check.NotNull(plugInSources, nameof(plugInSources));
    // 扫描模块
    var modules = GetDescriptors(services, startupModuleType, plugInSources);
    // 按照模块的依赖性重新排序
    modules = SortByDependency(modules, startupModuleType);
    return modules.ToArray();
}

生命周期

在上面第二步我们可以看到有一个await app.ConfigureServicesAsync();

  • 在这个方法中可以看到依次执行每个模块的PreConfigureServices,ConfigureServices,PostConfigureServices
public virtual async Task ConfigureServicesAsync()
    {
        CheckMultipleConfigureServices();

        var context = new ServiceConfigurationContext(Services);
        Services.AddSingleton(context);

        foreach (var module in Modules)
        {
            if (module.Instance is AbpModule abpModule)
            {
                abpModule.ServiceConfigurationContext = context;
            }
        }

        //PreConfigureServices
        foreach (var module in Modules.Where(m => m.Instance is IPreConfigureServices))
        {
            try
            {
                await ((IPreConfigureServices)module.Instance).PreConfigureServicesAsync(context);
            }
            catch (Exception ex)
            {
                throw new AbpInitializationException($"An error occurred during {nameof(IPreConfigureServices.PreConfigureServicesAsync)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
            }
        }

        var assemblies = new HashSet<Assembly>();

        //ConfigureServices
        foreach (var module in Modules)
        {
            if (module.Instance is AbpModule abpModule)
            {
                if (!abpModule.SkipAutoServiceRegistration)
                {
                    var assembly = module.Type.Assembly;
                    if (!assemblies.Contains(assembly))
                    {
                        Services.AddAssembly(assembly);
                        assemblies.Add(assembly);
                    }
                }
            }

            try
            {
                await module.Instance.ConfigureServicesAsync(context);
            }
            catch (Exception ex)
            {
                throw new AbpInitializationException($"An error occurred during {nameof(IAbpModule.ConfigureServicesAsync)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
            }
        }

        //PostConfigureServices
        foreach (var module in Modules.Where(m => m.Instance is IPostConfigureServices))
        {
            try
            {
                await ((IPostConfigureServices)module.Instance).PostConfigureServicesAsync(context);
            }
            catch (Exception ex)
            {
                throw new AbpInitializationException($"An error occurred during {nameof(IPostConfigureServices.PostConfigureServicesAsync)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
            }
        }

        foreach (var module in Modules)
        {
            if (module.Instance is AbpModule abpModule)
            {
                abpModule.ServiceConfigurationContext = null!;
            }
        }

        _configuredServices = true;
    }
  • 再次查看第四步中有一个services.AddCoreAbpServices(this, options);
    这个里面构造好其它的四个生命周期
internal static void AddCoreAbpServices(this IServiceCollection services,
    IAbpApplication abpApplication,
    AbpApplicationCreationOptions applicationCreationOptions)
{
    var moduleLoader = new ModuleLoader();
    var assemblyFinder = new AssemblyFinder(abpApplication);
    var typeFinder = new TypeFinder(assemblyFinder);
    if (!services.IsAdded<IConfiguration>())
    {
        services.ReplaceConfiguration(
            ConfigurationHelper.BuildConfiguration(
                applicationCreationOptions.Configuration
            )
        );
    }
    services.TryAddSingleton<IModuleLoader>(moduleLoader);
    services.TryAddSingleton<IAssemblyFinder>(assemblyFinder);
    services.TryAddSingleton<ITypeFinder>(typeFinder);
    services.TryAddSingleton<IInitLoggerFactory>(new DefaultInitLoggerFactory());
    services.AddAssemblyOf<IAbpApplication>();
    services.AddTransient(typeof(ISimpleStateCheckerManager<>), typeof(SimpleStateCheckerManager<>));
    // 注册生命周期
    services.Configure<AbpModuleLifecycleOptions>(options =>
    {
        // OnPreApplicationInitialization
        options.Contributors.Add<OnPreApplicationInitializationModuleLifecycleContributor>();
        // OnApplicationInitialization
        options.Contributors.Add<OnApplicationInitializationModuleLifecycleContributor>();
        // OnPostApplicationInitialization
        options.Contributors.Add<OnPostApplicationInitializationModuleLifecycleContributor>();
        // OnApplicationShutdown
        options.Contributors.Add<OnApplicationShutdownModuleLifecycleContributor>();
    });
}

注册了这四个生命周期,在什么时候调用呢?请继续往下看。

  1. 继续回到Startup类
public class Startup
{
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
    {
        app.InitializeApplication();
    }
}
  1. 查看InitializeApplication
  • 遍历刚刚注入的四个生命周期,执行Initialize初始化方法
public void InitializeModules(ApplicationInitializationContext context)
{
    foreach (var contributor in _lifecycleContributors)
    {
        foreach (var module in _moduleContainer.Modules)
        {
            try
            {
                contributor.Initialize(context, module.Instance);
            }
            catch (Exception ex)
            {
                //
            }
        }
    }
    _logger.LogInformation("Initialized all ABP modules.");
}

Abp vNext Pro

如果觉得可以,不要吝啬你的小星星哦

文章目录

与Abp vNext 模块加载机制相似的内容:

Abp vNext 模块加载机制

文章目录 生命周期 PreConfigureServices 添加依赖注入或者其它配置之前 ConfigureServices 添加依赖注入或者其它配置 PostConfigureServices 添加依赖注入或者其它配置之后 OnPreApplicationInitialization 初始化所有

Abp vNext 入门到放弃系列

文章目录 1.模块介绍 2.模块加载机制 3.依赖注入 4.AutoMapper-- 待定 5.本地化--待定 6.模型验证--待定 7.异常处理--待定 8.缓存 9.动态代理和拦截 10.分布式锁 11.领域驱动设计 Abp vNext Pro Abp Vnext Pro Github地址 的

Abp vNext 依赖注入

文章目录 介绍 ABP的依赖注入系统是基于Microsoft的依赖注入扩展库(Microsoft.Extensions.DependencyInjection nuget包)开发的。所以我们采用dotnet自带的注入方式也是支持的。 由于ABP是一个模块化框架,因此每个模块都定义它自己的服务并在它自

Skywalking APM监控系列(一丶.NET5.0+接入Skywalking监听)

前言 新项目采用的abp vnext的微服务模块化架构,所以把应用的服务拆成了很多独立模块 在初期,我们通过日志还能跟踪到问题, 后期服务越来越多(大约扩充到了十几个),随着调用链路越来越深 ,问题也越来越能排查了. 往往入口报错之后,要跟好几个服务的日志 才能找到最终节点. 所以考虑引入Skywa

迁移现有用户数据到ABP vNext

## 前言 使用 ABP vNext(下文简称 ABP)时,通常都是从 cli 开始新建模板,从一个空项目开始。对已经存续的项目来说,现有的数据,特别是用户等核心数据需要进行迁移。 老的项目,随着规模越来越大,每次修改都需要更改非常多地方,最重要的是,共用数据库使得维护起来需要小心翼翼。为了后续维护

ABP-VNext 用户权限管理系统实战06---实体的创建标准及迁移

在apb-vnext的实体的创建中可以确实字段的长度、说明、对应的表、表中给字段加的索引 以项目中的订单表为例,如下: [Comment("订单主表")] [Table("t_voucher_order")] [Index(nameof(VoucherCode))] public class Ord

OData WebAPI实践-与ABP vNext集成

本文属于 OData 系列文章 ABP 是一个流行的 ASP. NET 开发框架,旧版的的 ABP 已经能够非常好的支持了 OData ,并提供了对应的 OData 包。 ABP vNext 是一个重新设计的,面向微服务的框架,提供了一些非常有用的特性,包括分页查询等但是它并不能原生支持 OData

abp 创建DDD项目

abp 创建DDD项目 我和我的伙伴在搭建框架的基础框架,找了很多框架,最后选择用abp作为DDD的规范标准。 创建项目 1.命令行中安装 ABP CLI: dotnet tool install -g Volo.Abp.Cli 2.查看abp 版本: abp -v 3.如果版本过低,更新版本,目前

aspnetcore插件开发dll热加载 二

这一篇文章应该是个总结。 投简历的时候是不是有人问我有没有abp的开发经历,汗颜! 在各位大神的尝试及自己的总结下,还是实现了业务和主机服务分离,通过dll动态的加载卸载,控制器动态的删除添加。 项目如下: 演示效果: 下面就是代码部分: 重点 1.IActionDescriptorChangePr