比较随意,记录下过程,以便忘了以后重拾。

三个关注点

Program.cs

      internal static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac() // 第一个关注点
.UseSerilog();
    public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<AuthCenterWebModule>(); // 第二个关注点
} public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.InitializeApplication(); // 第三个关注点
}
}

services.AddApplication()过程

        public static IAbpApplicationWithExternalServiceProvider AddApplication<TStartupModule>(
[NotNull] this IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
where TStartupModule : IAbpModule
{
// Factory工厂创建AbpApplication
return AbpApplicationFactory.Create<TStartupModule>(services, optionsAction);
}
        public static IAbpApplicationWithExternalServiceProvider Create<TStartupModule>(
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
where TStartupModule : IAbpModule
{
return Create(typeof(TStartupModule), services, optionsAction);
} public static IAbpApplicationWithExternalServiceProvider Create(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
{
// 这里创建具体实例
return new AbpApplicationWithExternalServiceProvider(startupModuleType, services, optionsAction);
}

查看AbpApplicationWithExternalServiceProvider构造函数

        public AbpApplicationWithExternalServiceProvider(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction
) : base(
startupModuleType,
services,
optionsAction)
{
// 注入自己,初始化在基类,继续查看基类
services.AddSingleton<IAbpApplicationWithExternalServiceProvider>(this);
}
        internal AbpApplicationBase(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction)
{
Check.NotNull(startupModuleType, nameof(startupModuleType));
Check.NotNull(services, nameof(services)); StartupModuleType = startupModuleType;
Services = services; services.TryAddObjectAccessor<IServiceProvider>(); var options = new AbpApplicationCreationOptions(services);
optionsAction?.Invoke(options); services.AddSingleton<IAbpApplication>(this);
services.AddSingleton<IModuleContainer>(this); services.AddCoreServices();
services.AddCoreAbpServices(this, options); // 以上都是注入服务 // 加载模块,Modules的模块是按依赖顺序的排序
Modules = LoadModules(services, options);
// 主要看这里,服务配置
ConfigureServices();
}
        protected virtual void ConfigureServices()
{
// 将ServiceCollection传入ServiceConfigurationContext
var context = new ServiceConfigurationContext(Services);
Services.AddSingleton(context); foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
// 为每个模块实例设定context, 这样通过每个模块通过上下文都可以访问ServiceCollection
abpModule.ServiceConfigurationContext = context;
}
} // 依次调用每个模块的PreConfigureServices, ConfigureServices, PostConfigureServices //PreConfigureServices
foreach (var module in Modules.Where(m => m.Instance is IPreConfigureServices))
{
try
{
((IPreConfigureServices)module.Instance).PreConfigureServices(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IPreConfigureServices.PreConfigureServices)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
}
} //ConfigureServices
foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
// 执行约定注入
if (!abpModule.SkipAutoServiceRegistration)
{
Services.AddAssembly(module.Type.Assembly);
}
} try
{
module.Instance.ConfigureServices(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IAbpModule.ConfigureServices)} 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
{
((IPostConfigureServices)module.Instance).PostConfigureServices(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IPostConfigureServices.PostConfigureServices)} 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;
}
}
}

小结

以上实现了每个模块服务的注入,即所有模块执行PreConfigureServices,完成后所有模块执行ConfigureServices,完成后所有模块执行PostConfigureServices。

PreConfigureServices即服务注入还没开始,这里可以做些什么?

ConfigureServices注入,

PostConfigureServices所有服务已注入,这里可以做些什么?

    public class AuthCenterDomainModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{ } public override void ConfigureServices(ServiceConfigurationContext context)
{ } public override void PostConfigureServices(ServiceConfigurationContext context)
{ }
}

ABP源码分析 - 服务配置(1)的更多相关文章

  1. C# DateTime的11种构造函数 [Abp 源码分析]十五、自动审计记录 .Net 登陆的时候添加验证码 使用Topshelf开发Windows服务、记录日志 日常杂记——C#验证码 c#_生成图片式验证码 C# 利用SharpZipLib生成压缩包 Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库

    C# DateTime的11种构造函数   别的也不多说没直接贴代码 using System; using System.Collections.Generic; using System.Glob ...

  2. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  3. ABP源码分析二:ABP中配置的注册和初始化

    一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数的执行必然是完成 ...

  4. ABP源码分析四十四:ZERO的配置

    ABP Zero模块中需要配置的地方主要集中在三块:配置静态的role,配置外部认证源,以及配置本地化语言和资源. UserManagementConfig/IUserManagementConfig ...

  5. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  6. ABP源码分析四:Configuration

    核心模块的配置 Configuration是ABP中设计比较巧妙的地方.其通过AbpStartupConfiguration,Castle的依赖注入,Dictionary对象和扩展方法很巧妙的实现了配 ...

  7. ABP源码分析七:Setting 以及 Mail

    本文主要说明Setting的实现以及Mail这个功能模块如何使用Setting. 首先区分一下ABP中的Setting和Configuration. Setting一般用于需要通过外部配置文件(或数据 ...

  8. ABP源码分析九:后台工作任务

    文主要说明ABP中后台工作者模块(BackgroundWorker)的实现方式,和后台工作模块(BackgroundJob).ABP通过BackgroundWorkerManager来管理Backgr ...

  9. ABP源码分析十二:本地化

    本文逐个分析ABP中涉及到locaization的接口和类,以及相互之间的关系.本地化主要涉及两个方面:一个是语言(Language)的管理,这部分相对简单.另一个是语言对应得本地化资源(Locali ...

随机推荐

  1. php 23种设计模型 - 桥接模式

    桥接模式(Bridge) 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化.这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦. 这种模式涉 ...

  2. LGP4587题解

    遇到一道题,我们该做什么? 打暴力. 此题的暴力是什么?从小到大枚举答案.但这太慢了,需要一个结论来加速一下: 若 \([1,x]\) 都能够被表示出来,新加入一个数 \(y\),若 \(y>x ...

  3. HCIE数据挖掘笔记-005数据挖掘专业名词

    数据对象和属性类别: 数据一般有噪声,数量庞大,且来自不同的数据源 数据集由数据对象组成,一个数据对象代表一个实体 数据对象:样本.实例.数据点.对象 数据对象以数据元组的形式存放在数据库中,数据库的 ...

  4. SpringCloud微服务之Ribbon负载均衡(一)

    什么是微服务?什么是SpringCloud? 微服务是一种架构的模式,它提倡将一个应用程序划分成很多个微小的服务,服务与服务之间相互协调.相互配合.每个服务运行都是一个独立的进程,服务与服务之间采用轻 ...

  5. Java实例变量、局部变量、静态变量

    实例变量(成员变量) 成员变量定义在类中,在整个类中都可以被访问,但在方法.构造方法和语句块之外 当一个对象被实例化之后,每个实例变量的值就跟着确定 实例变量在对象创建的时候创建,在对象被销毁时销毁 ...

  6. ArcMap操作随记(7)

    1.栅格分辨率调整 [重采样] 2.点集数据对插值模型精度检验 test数据→[子集要素](地统计分析)→train→[插值]→[多值提取至点]→[字段计算器](Abs([value]-[spline ...

  7. 闲聊系列之 5-why root cause分析法

    本篇参考: https://max.book118.com/html/2017/1126/141669829.shtm https://baike.baidu.com/item/5why%E5%88% ...

  8. [SPDK/NVMe存储技术分析]007 - 初识UIO

    注: 要进一步搞清楚SSD盘对应的PCI的BAR寄存器的映射,有必要先了解一下UIO(Userspace I/O). UIO(Userspace I/O)是运行在用户空间的I/O技术.在Linux系统 ...

  9. 程序语言与编程实践4-> 蓝桥杯C/C++备赛记录2 | 第二周学习训练

    0323,又是一周星期三,按道理该总结了.这周前几天写题比较多,后面事情多了起来,就没怎么写了.主要方向是洛谷的基本语法熟悉,PTA平台数据结构的一些题目. 0323附上: 题目比较多,所以文章可能有 ...

  10. Redis数据结构详解(1)-redis中的字符串(SDS)

    前提知识 我们先从百科上摘下Redis的解释: Redis是一个使用ANSI C编写的开源.支持网络.基于内存.分布式.可选持久性的键值对存储数据库. (不用过多在意ANSI,它只是一个标准,你可以理 ...