介绍
此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。
通过解读ABP源码,可以提升ABP使用方式,可以提升编码意识,提高面向对象编程思想。
此篇文章主要解读ABP框架的启动过程已经相关类。
ABP启动
通过测试代码AbpBootstraper_Tester
可以一窥ABP启动类的使用方式
由测试代码可知,要启动abp框架,主要是使用类AbpBootstrapper
,经过如下步骤
- 定义启动模块
- 创建
AbpBootstrapper
类实例 - 使用启动模块初始化
AbpBootstrapper
类的实例 - 调用
AbpBootstrapper
的初始化代码Initialize
源码结构图
启动过程
1. 创建启动实例
///
/// Creates a new instance.
/// 创建 实例
///
///
/// Startup module of the application which depends on other used modules. Should be derived from .
/// 应用程序启用的模块
///
/// An action to set options
/// 启动选项
///
private AbpBootstrapper([NotNull] Type startupModule, [CanBeNull] Action 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();
}
}
///
/// Creates a new instance.
/// 创建 实例
///
///
/// Startup module of the application which depends on other used modules. Should be derived from .
/// 启动模块类
///
/// An action to set options
/// 启动选项
///
public static AbpBootstrapper Create([CanBeNull] Action optionsAction = null)
where TStartupModule : AbpModule
{
return new AbpBootstrapper(typeof(TStartupModule), optionsAction);
}
///
/// Creates a new instance.
///
///
/// Startup module of the application which depends on other used modules. Should be derived from .
/// 启动模块类的类型
///
///
/// An action to set options
/// 启动选项
///
public static AbpBootstrapper Create([NotNull] Type startupModule, [CanBeNull] Action optionsAction = null)
{
return new AbpBootstrapper(startupModule, optionsAction);
}
///
/// 注册AOP拦截器
///
private void AddInterceptorRegistrars()
{
ValidationInterceptorRegistrar.Initialize(IocManager);
AuditingInterceptorRegistrar.Initialize(IocManager);
EntityHistoryInterceptorRegistrar.Initialize(IocManager);
UnitOfWorkRegistrar.Initialize(IocManager);
AuthorizationInterceptorRegistrar.Initialize(IocManager);
}
通过调用Create
或者Create
创建AbpBootstrapper
实例,AbpBootstrapper
的构造方法是private
,这也意味着,只能通过这两个方式,创建AbpBootstrapper
实例。
在AbpBootstrapper
构造函数中,主要做了一下几件事:
- 检查启动模块是否继承
AbpModule
- 设置启动类中的启动模块
- 设置启动类中的Ioc管理器
- 设置插件来源列表
- 启用拦截器(根据选项确定是否启用)
2. 程序初始化
调用AbpBootstrapper
的初始化代码Initialize
///
/// Initializes the ABP system.
/// 初始化ABP系统
///
public virtual void Initialize()
{
// 解析日志组件,以便记录启动过程
ResolveLogger();
try
{
// 注册启动类
RegisterBootstrapper();
// 注册ABP组件
IocManager.IocContainer.Install(new AbpCoreInstaller());
// 加载插件
IocManager.Resolve().PlugInSources.AddRange(PlugInSources);
// 初始化启动配置
IocManager.Resolve().Initialize();
// 初始化模块管理器
_moduleManager = IocManager.Resolve();
// 初始化模块
_moduleManager.Initialize(StartupModule);
// 启动模块
_moduleManager.StartModules();
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString(), ex);
throw;
}
}
///
/// 解析日志组件
///
private void ResolveLogger()
{
if (IocManager.IsRegistered())
{
_logger = IocManager.Resolve().Create(typeof(AbpBootstrapper));
}
}
///
/// 注册启动类
///
private void RegisterBootstrapper()
{
if (!IocManager.IsRegistered())
{
// 注册自身实例到ioc容器
IocManager.IocContainer.Register(
Component.For().Instance(this)
);
}
}
在初始化方法中,主要进行一下内容
- 从ioc容器中解析日志组件,以便记录启动过程
- 在Ioc容器中注册启动类自身实例
- 注册ABP组件
- 加载插件
- 启动配置初始化
- 初始化模块管理器
- 初始化启动模块
- 启动模块
启动模块之后,整个ABP系统就已经启动完毕.
设计模式
简单工厂设计模式
创建AbpBootstrapper
使用了简单工厂设计模式,设置构造函数为private,使得外部环境只能使用static方法创建实例。
对于AbpBootstrapper
而言,该类自身就是一个工厂类,根据具体的方法返回AbpBootstrapper
实例。
测试代码
public class AbpBootstraper_Tester : TestBaseWithLocalIocManager
{
private readonly AbpBootstrapper _bootstrapper;
public AbpBootstraper_Tester()
{
_bootstrapper = AbpBootstrapper.Create(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();
var otherModule = LocalIocManager.Resolve();
var anotherModule = LocalIocManager.Resolve();
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 class 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 class MyOtherModule : MyEventCounterModuleBase
{
public int CallMeOnStartupCount { get; private set; }
public void CallMeOnStartup()
{
CallMeOnStartupCount++;
}
}
public class MyAnotherModule : MyEventCounterModuleBase
{
}
public abstract class 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是否正常初始化和模块是否正常被调用。