ABP源码分析 - 服务配置(1)
比较随意,记录下过程,以便忘了以后重拾。
三个关注点
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)
{
}
}