美文网首页ABP
ABP 源码解析 一. ABP启动

ABP 源码解析 一. ABP启动

作者: 诸葛_小亮 | 来源:发表于2018-08-06 21:49 被阅读57次

    介绍

    此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。
    通过解读ABP源码,可以提升ABP使用方式,可以提升编码意识,提高面向对象编程思想。

    此篇文章主要解读ABP框架的启动过程已经相关类。


    ABP启动

    通过测试代码AbpBootstraper_Tester可以一窥ABP启动类的使用方式

    abp启动测试代码
    abp启动测试运行结果

    由测试代码可知,要启动abp框架,主要是使用类AbpBootstrapper,经过如下步骤

    1. 定义启动模块
    2. 创建AbpBootstrapper类实例
    3. 使用启动模块初始化AbpBootstrapper类的实例
    4. 调用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 class 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 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是否正常初始化和模块是否正常被调用。


    我的公众号

    相关文章

      网友评论

        本文标题:ABP 源码解析 一. ABP启动

        本文链接:https://www.haomeiwen.com/subject/vhxvvftx.html