ABP 源码解析 一. ABP启动
时间:2022-09-23
介绍
此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。
通过解读ABP源码,可以提升ABP使用方式,可以提升编码意识,提高面向对象编程思想。
此篇文章主要解读ABP框架的启动过程已经相关类。
ABP启动
通过测试代码AbpBootstraper_Tester
可以一窥ABP启动类的使用方式
abp启动测试代码
abp启动测试运行结果
由测试代码可知,要启动abp框架,主要是使用类AbpBootstrapper
,经过如下步骤
- 定义启动模块
- 创建
AbpBootstrapper
类实例 - 使用启动模块初始化
AbpBootstrapper
类的实例 - 调用
AbpBootstrapper
的初始化代码Initialize
源码结构图
AbpBootstrapper
AbpBootstrapperOptions
启动过程
1. 创建启动实例
/// <summary>
/// Creates a new <see cref="AbpBootstrapper"/> instance.
/// 创建<see cref="AbpBootstrapper"/>实例
/// </summary>
/// <param name="startupModule">
/// Startup module of the application which depends on other used modules. Should be derived from <see cref="AbpModule"/>.
/// 应用程序启用的模块
/// </param>
/// <param name="optionsAction">An action to set options
/// 启动选项
/// </param>
private AbpBootstrapper([NotNull] Type startupModule, [CanBeNull] Action<AbpBootstrapperOptions> optionsAction = null)
{
Check.NotNull(startupModule, nameof(startupModule));
var options = new AbpBootstrapperOptions();
optionsAction?.Invoke(options);
// 检查启动模块是否继承AbpModule
if (!typeof(AbpModule).GetTypeInfo().IsAssignableFrom(startupModule))
{
throw new ArgumentException($"{nameof(startupModule)} should be derived from {nameof(AbpModule)}.");
}
// 设置启动模块
StartupModule = startupModule;
// 设置Ioc管理器
IocManager = options.IocManager;
// 设置插件来源
PlugInSources = options.PlugInSources;
_logger = NullLogger.Instance;
// 根据选项配置是否加载拦截器
if (!options.DisableAllInterceptors)
{
AddInterceptorRegistrars();
}
}
/// <summary>
/// Creates a new <see cref="AbpBootstrapper"/> instance.
/// 创建<see cref="AbpBootstrapper"/>实例
/// </summary>
/// <typeparam name="TStartupModule">
/// Startup module of the application which depends on other used modules. Should be derived from <see cref="AbpModule"/>.
/// 启动模块类
/// </typeparam>
/// <param name="optionsAction">An action to set options
/// 启动选项
/// </param>
public static AbpBootstrapper Create<TStartupModule>([CanBeNull] Action<AbpBootstrapperOptions> optionsAction = null)
where TStartupModule : AbpModule
{
return new AbpBootstrapper(typeof(TStartupModule), optionsAction);
}
/// <summary>
/// Creates a new <see cref="AbpBootstrapper"/> instance.
/// </summary>
/// <param name="startupModule">
/// Startup module of the application which depends on other used modules. Should be derived from <see cref="AbpModule"/>.
/// 启动模块类的类型
/// </param>
/// <param name="optionsAction">
/// An action to set options
/// 启动选项
/// </param>
public static AbpBootstrapper Create([NotNull] Type startupModule, [CanBeNull] Action<AbpBootstrapperOptions> optionsAction = null)
{
return new AbpBootstrapper(startupModule, optionsAction);
}
/// <summary>
/// 注册AOP拦截器
/// </summary>
private void AddInterceptorRegistrars()
{
ValidationInterceptorRegistrar.Initialize(IocManager);
AuditingInterceptorRegistrar.Initialize(IocManager);
EntityHistoryInterceptorRegistrar.Initialize(IocManager);
UnitOfWorkRegistrar.Initialize(IocManager);
AuthorizationInterceptorRegistrar.Initialize(IocManager);
}
通过调用Create<TStartupModule>
或者Create
创建AbpBootstrapper
实例,AbpBootstrapper
的构造方法是private
,这也意味着,只能通过这两个方式,创建AbpBootstrapper
实例。
在AbpBootstrapper
构造函数中,主要做了一下几件事:
- 检查启动模块是否继承
AbpModule
- 设置启动类中的启动模块
- 设置启动类中的Ioc管理器
- 设置插件来源列表
- 启用拦截器(根据选项确定是否启用)
2. 程序初始化
调用AbpBootstrapper
的初始化代码Initialize
/// <summary>
/// Initializes the ABP system.
/// 初始化ABP系统
/// </summary>
public virtual void Initialize()
{
// 解析日志组件,以便记录启动过程
ResolveLogger();
try
{
// 注册启动类
RegisterBootstrapper();
// 注册ABP组件
IocManager.IocContainer.Install(new AbpCoreInstaller());
// 加载插件
IocManager.Resolve<AbpPlugInManager>().PlugInSources.AddRange(PlugInSources);
// 初始化启动配置
IocManager.Resolve<AbpStartupConfiguration>().Initialize();
// 初始化模块管理器
_moduleManager = IocManager.Resolve<AbpModuleManager>();
// 初始化模块
_moduleManager.Initialize(StartupModule);
// 启动模块
_moduleManager.StartModules();
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString(), ex);
throw;
}
}
/// <summary>
/// 解析日志组件
/// </summary>
private void ResolveLogger()
{
if (IocManager.IsRegistered<ILoggerFactory>())
{
_logger = IocManager.Resolve<ILoggerFactory>().Create(typeof(AbpBootstrapper));
}
}
/// <summary>
/// 注册启动类
/// </summary>
private void RegisterBootstrapper()
{
if (!IocManager.IsRegistered<AbpBootstrapper>())
{
// 注册自身实例到ioc容器
IocManager.IocContainer.Register(
Component.For<AbpBootstrapper>().Instance(this)
);
}
}
在初始化方法中,主要进行一下内容
- 从ioc容器中解析日志组件,以便记录启动过程
- 在Ioc容器中注册启动类自身实例
- 注册ABP组件
- 加载插件
- 启动配置初始化
- 初始化模块管理器
- 初始化启动模块
- 启动模块
启动模块之后,整个ABP系统就已经启动完毕.
设计模式
简单工厂设计模式
创建AbpBootstrapper
使用了简单工厂设计模式,设置构造函数为private,使得外部环境只能使用static方法创建实例。
对于AbpBootstrapper
而言,该类自身就是一个工厂类,根据具体的方法返回AbpBootstrapper
实例。
测试代码
public >AbpBootstraper_Tester : TestBaseWithLocalIocManager
{
private readonly AbpBootstrapper _bootstrapper;
public AbpBootstraper_Tester()
{
_bootstrapper = AbpBootstrapper.Create<MyTestModule>(options =>
{
options.IocManager = LocalIocManager;
});
}
[Fact(DisplayName = "ABP初始化")]
public void Should_Initialize_Bootstrapper()
{
_bootstrapper.Initialize();
}
[Fact(DisplayName = "ABP启动时初始化模块")]
public void Should_Call_Module_Events_Once()
{
_bootstrapper.Initialize();
_bootstrapper.Dispose();
var testModule = LocalIocManager.Resolve<MyTestModule>();
var otherModule = LocalIocManager.Resolve<MyOtherModule>();
var anotherModule = LocalIocManager.Resolve<MyAnotherModule>();
testModule.PreInitializeCount.ShouldBe(1);
testModule.InitializeCount.ShouldBe(1);
testModule.PostInitializeCount.ShouldBe(1);
testModule.ShutdownCount.ShouldBe(1);
otherModule.PreInitializeCount.ShouldBe(1);
otherModule.InitializeCount.ShouldBe(1);
otherModule.PostInitializeCount.ShouldBe(1);
otherModule.ShutdownCount.ShouldBe(1);
otherModule.CallMeOnStartupCount.ShouldBe(1);
anotherModule.PreInitializeCount.ShouldBe(1);
anotherModule.InitializeCount.ShouldBe(1);
anotherModule.PostInitializeCount.ShouldBe(1);
anotherModule.ShutdownCount.ShouldBe(1);
}
public override void Dispose()
{
_bootstrapper.Dispose();
base.Dispose();
}
}
[DependsOn(typeof(MyOtherModule))]
[DependsOn(typeof(MyAnotherModule))]
public >MyTestModule : MyEventCounterModuleBase
{
private readonly MyOtherModule _otherModule;
public MyTestModule(MyOtherModule otherModule)
{
_otherModule = otherModule;
}
public override void PreInitialize()
{
base.PreInitialize();
_otherModule.PreInitializeCount.ShouldBe(1);
_otherModule.CallMeOnStartup();
}
public override void Initialize()
{
base.Initialize();
_otherModule.InitializeCount.ShouldBe(1);
}
public override void PostInitialize()
{
base.PostInitialize();
_otherModule.PostInitializeCount.ShouldBe(1);
}
public override void Shutdown()
{
base.Shutdown();
_otherModule.ShutdownCount.ShouldBe(0); //Depended module should be shutdown after this module
}
}
public >MyOtherModule : MyEventCounterModuleBase
{
public int CallMeOnStartupCount { get; private set; }
public void CallMeOnStartup()
{
CallMeOnStartupCount++;
}
}
public >MyAnotherModule : MyEventCounterModuleBase
{
}
public abstract >MyEventCounterModuleBase : AbpModule
{
public int PreInitializeCount { get; private set; }
public int InitializeCount { get; private set; }
public int PostInitializeCount { get; private set; }
public int ShutdownCount { get; private set; }
public override void PreInitialize()
{
IocManager.ShouldNotBe(null);
Configuration.ShouldNotBe(null);
PreInitializeCount++;
}
public override void Initialize()
{
InitializeCount++;
}
public override void PostInitialize()
{
PostInitializeCount++;
}
public override void Shutdown()
{
ShutdownCount++;
}
}
测试运行结果
运行结果
该测试主要测试ABP是否正常初始化和模块是否正常被调用。
我的公众号
特别声明:本站部分内容收集于互联网是出于更直观传递信息的目的。该内容版权归原作者所有,并不代表本站赞同其观点和对其真实性负责。如该内容涉及任何第三方合法权利,请及时与824310991@qq.com联系,我们会及时反馈并处理完毕。