模塊Module是ABP框架體系很重要的概念,不同的功能組件包括項目之間都是以模塊的形式進行關聯的。在ABP框架的啓動過程中,模塊的遍歷、初始化、啓動也是很重要的一環。
1.模塊的定義
1.1定義
在ABP框架中定義了基類AbpModule,只要是繼承自AbpModule的類就是模塊。先來看看這個基類的定義。
namespace Abp.Modules
{
public abstract class AbpModule
{
//獲取對IOC管理器的引用
protected internal IIocManager IocManager { get; internal set; }
// 獲取對ABP配置項的引用
protected internal IAbpStartupConfiguration Configuration { get; internal set; }
// 獲取或設置日誌
public ILogger Logger { get; set; }
protected AbpModule()
{
Logger = NullLogger.Instance;
}
// 預初始化
public virtual void PreInitialize()
{
}
// 初始化
public virtual void Initialize()
{
}
//初始化後
public virtual void PostInitialize()
{
}
// 關閉
public virtual void Shutdown()
{
}
public virtual Assembly[] GetAdditionalAssemblies()
{
return new Assembly[0];
}
// 檢查是否爲模塊
public static bool IsAbpModule(Type type)
{
var typeInfo = type.GetTypeInfo();
return
typeInfo.IsClass &&
!typeInfo.IsAbstract &&
!typeInfo.IsGenericType &&
typeof(AbpModule).IsAssignableFrom(type);
}
// 查找依賴模塊
public static List<Type> FindDependedModuleTypes(Type moduleType)
{
if (!IsAbpModule(moduleType))
{
throw new AbpInitializationException("This type is not an ABP module: " + moduleType.AssemblyQualifiedName);
}
var list = new List<Type>();
if (moduleType.GetTypeInfo().IsDefined(typeof(DependsOnAttribute), true))
{
var dependsOnAttributes = moduleType.GetTypeInfo().GetCustomAttributes(typeof(DependsOnAttribute), true).Cast<DependsOnAttribute>();
foreach (var dependsOnAttribute in dependsOnAttributes)
{
foreach (var dependedModuleType in dependsOnAttribute.DependedModuleTypes)
{
list.Add(dependedModuleType);
}
}
}
return list;
}
//根據給定的模塊遞歸查找其所依賴的模塊
public static List<Type> FindDependedModuleTypesRecursivelyIncludingGivenModule(Type moduleType)
{
var list = new List<Type>();
AddModuleAndDependenciesRecursively(list, moduleType);
list.AddIfNotContains(typeof(AbpKernelModule));
return list;
}
//遞歸添加模塊和依賴
private static void AddModuleAndDependenciesRecursively(List<Type> modules, Type module)
{
if (!IsAbpModule(module))
{
throw new AbpInitializationException("This type is not an ABP module: " + module.AssemblyQualifiedName);
}
if (modules.Contains(module))
{
return;
}
modules.Add(module);
var dependedModules = FindDependedModuleTypes(module);
foreach (var dependedModule in dependedModules)
{
AddModuleAndDependenciesRecursively(modules, dependedModule);
}
}
}
}
在AbpModule中可以看到其內部以接口形式定義了IoC管理器、模塊配置項和日誌組件,此外還有模塊的生命週期事件和查找當前模塊所依賴模塊的方法。
1.2生命週期
在AbpModule可以看到模塊的四個生命週期事件:
生命週期事件 | 說明 |
---|---|
PreInitialize | 預初始化:在初始化之前配置框架和其他模塊。能夠在依賴注入註冊之前,在這個方法中指定需要注入的自定義啓動類 |
Initialize | 初始化:一般是來進行依賴注入的註冊,常通過 IocManager.RegisterAssemblyByConvention 來實現 |
PostInitialize | 初始化後:用來解析依賴關係 |
Shutdown | 關閉:當應用關閉以後被調用 |
對於任意一個模塊,這四個方法的執行順序依次爲PreInitialize–>Initialize–>PostInitialize–>Shutdown。
2.模塊的依賴
2.1特性
ABP框架提供了DependsOn屬性來顯式說明模塊間的依賴關係。可以看到DependsOn屬性支持的是數組,所以一個模塊可以依賴於多個模塊。
namespace Abp.Modules
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class DependsOnAttribute : Attribute
{
public Type[] DependedModuleTypes { get; private set; }
public DependsOnAttribute(params Type[] dependedModuleTypes)
{
DependedModuleTypes = dependedModuleTypes;
}
}
}
再來看看示例解決方案中各模塊的依賴關係。
//Web項目--呈現與分佈式服務層
[DependsOn(
typeof(AbpDemoApplicationModule),
typeof(AbpDemoEntityFrameworkCoreModule),
typeof(AbpAspNetCoreModule))]
public class AbpDemoWebModule : AbpModule
{
//to do
}
//EntityFrameworkCore項目--基礎設施層
[DependsOn(
typeof(AbpDemoCoreModule),
typeof(AbpEntityFrameworkCoreModule))]
public class AbpDemoEntityFrameworkCoreModule : AbpModule
{
// to do
}
//Application項目--應用層
[DependsOn(
typeof(AbpDemoCoreModule),
typeof(AbpAutoMapperModule))]
public class AbpDemoApplicationModule : AbpModule
{
// to do
}
//Core項目--領域層
public class AbpDemoCoreModule : AbpModule
{
// to do
}
3.模塊的啓動
3.1啓動順序
對於每個模塊都用同樣的生命週期事件,但是有多個模塊而且這些模塊互相之間存在依賴關係時,這些生命週期事件又該如何執行?對於這種情況,ABP框架作了清晰的定義:所有模塊執行完PreInitialize預初始化方法後,所有模塊再執行Initialize初始化方法,之後所有模塊再執行PostInitialize初始化後方法。在ABP框架的啓動過程中也遵循這一流程。
現在再回到AbpBootstrapper的Initialize初始化方法中,仔細查看模塊啓動的全過程。
_moduleManager = IocManager.Resolve<AbpModuleManager>();
_moduleManager.Initialize(StartupModule);
_moduleManager.StartModules();
3.1.1 實例化模塊管理器
3.1.2 初始化模塊管理器
public virtual void Initialize(Type startupModule)
{
_modules = new AbpModuleCollection(startupModule);
LoadAllModules();
}
private void LoadAllModules()
{
Logger.Debug("Loading Abp modules...");
List<Type> plugInModuleTypes;
var moduleTypes = FindAllModuleTypes(out plugInModuleTypes).Distinct().ToList();
Logger.Debug("Found " + moduleTypes.Count + " ABP modules in total.");
RegisterModules(moduleTypes);
CreateModules(moduleTypes, plugInModuleTypes);
_modules.EnsureKernelModuleToBeFirst();
_modules.EnsureStartupModuleToBeLast();
SetDependencies();
Logger.DebugFormat("{0} modules loaded.", _modules.Count);
}
3.1.3啓動模塊
public virtual void StartModules()
{
var sortedModules = _modules.GetSortedModuleListByDependency();
sortedModules.ForEach(module => module.Instance.PreInitialize());
sortedModules.ForEach(module => module.Instance.Initialize());
sortedModules.ForEach(module => module.Instance.PostInitialize());
}
3.2 AbpKernelModule
public sealed class AbpKernelModule : AbpModule
{
public override void PreInitialize()
{
//註冊過濾器與基礎組件
IocManager.AddConventionalRegistrar(new BasicConventionalRegistrar());
IocManager.Register<IScopedIocResolver, ScopedIocResolver>(DependencyLifeStyle.Transient);
IocManager.Register(typeof(IAmbientScopeProvider<>), typeof(DataContextAmbientScopeProvider<>), DependencyLifeStyle.Transient);
AddAuditingSelectors();
AddLocalizationSources();
AddSettingProviders();
AddUnitOfWorkFilters();
ConfigureCaches();
AddIgnoredTypes();
AddMethodParameterValidators();
AddDefaultNotificationDistributor();
}
public override void Initialize()
{
//
foreach (var replaceAction in ((AbpStartupConfiguration)Configuration).ServiceReplaceActions.Values)
{
replaceAction();
}
IocManager.IocContainer.Install(new EventBusInstaller(IocManager));
IocManager.Register(typeof(IOnlineClientManager<>), typeof(OnlineClientManager<>), DependencyLifeStyle.Singleton);
IocManager.Register(typeof(IOnlineClientStore<>), typeof(InMemoryOnlineClientStore<>), DependencyLifeStyle.Singleton);
IocManager.Register(typeof(EventTriggerAsyncBackgroundJob<>), DependencyLifeStyle.Transient);
IocManager.RegisterAssemblyByConvention(typeof(AbpKernelModule).GetAssembly(),
new ConventionalRegistrationConfig
{
InstallInstallers = false
});
}
public override void PostInitialize()
{
RegisterMissingComponents();
IocManager.Resolve<SettingDefinitionManager>().Initialize();
IocManager.Resolve<FeatureManager>().Initialize();
IocManager.Resolve<PermissionManager>().Initialize();
IocManager.Resolve<LocalizationManager>().Initialize();
IocManager.Resolve<NotificationDefinitionManager>().Initialize();
IocManager.Resolve<NavigationManager>().Initialize();
if (Configuration.BackgroundJobs.IsJobExecutionEnabled)
{
var workerManager = IocManager.Resolve<IBackgroundWorkerManager>();
workerManager.Start();
workerManager.Add(IocManager.Resolve<IBackgroundJobManager>());
}
}
}