ABP中模块初始化过程(二)

在上一篇介绍在StartUp类中的ConfigureService()中的AddAbp方法后我们再来重点说一说在Configure()方法中的UserAbp()方法,还是和前面的一样我们来通过代码来进行一步步分析。

 public static class AbpApplicationBuilderExtensions
    {
        public static void UseAbp(this IApplicationBuilder app)
        {
            app.UseAbp(null);
        }

        public static void UseAbp([NotNull] this IApplicationBuilder app, Action<AbpApplicationBuilderOptions> optionsAction)
        {
            Check.NotNull(app, nameof(app));

            var options = new AbpApplicationBuilderOptions();
            optionsAction?.Invoke(options);

            if (options.UseCastleLoggerFactory)
            {
                app.UseCastleLoggerFactory();
            }

            InitializeAbp(app);

            if (options.UseAbpRequestLocalization)
            {
                //TODO: This should be added later than authorization middleware!
                app.UseAbpRequestLocalization();
            }

            if (options.UseSecurityHeaders)
            {
                app.UseAbpSecurityHeaders();
            }
        }

        public static void UseEmbeddedFiles(this IApplicationBuilder app)
        {
            app.UseStaticFiles(
                new StaticFileOptions
                {
                    FileProvider = new EmbeddedResourceFileProvider(
                        app.ApplicationServices.GetRequiredService<IIocResolver>()
                    )
                }
            );
        }

        private static void InitializeAbp(IApplicationBuilder app)
        {
            var abpBootstrapper = app.ApplicationServices.GetRequiredService<AbpBootstrapper>();
            abpBootstrapper.Initialize();

            var applicationLifetime = app.ApplicationServices.GetService<IApplicationLifetime>();
            applicationLifetime.ApplicationStopping.Register(() => abpBootstrapper.Dispose());
        }

        public static void UseCastleLoggerFactory(this IApplicationBuilder app)
        {
            var castleLoggerFactory = app.ApplicationServices.GetService<Castle.Core.Logging.ILoggerFactory>();
            if (castleLoggerFactory == null)
            {
                return;
            }

            app.ApplicationServices
                .GetRequiredService<ILoggerFactory>()
                .AddCastleLogger(castleLoggerFactory);
        }

        public static void UseAbpRequestLocalization(this IApplicationBuilder app, Action<RequestLocalizationOptions> optionsAction = null)
        {
            var iocResolver = app.ApplicationServices.GetRequiredService<IIocResolver>();
            using (var languageManager = iocResolver.ResolveAsDisposable<ILanguageManager>())
            {
                var supportedCultures = languageManager.Object
                    .GetLanguages()
                    .Select(l => CultureInfo.GetCultureInfo(l.Name))
                    .ToArray();

                var options = new RequestLocalizationOptions
                {
                    SupportedCultures = supportedCultures,
                    SupportedUICultures = supportedCultures
                };

                var userProvider = new AbpUserRequestCultureProvider();

                //0: QueryStringRequestCultureProvider
                options.RequestCultureProviders.Insert(1, userProvider);
                options.RequestCultureProviders.Insert(2, new AbpLocalizationHeaderRequestCultureProvider());
                //3: CookieRequestCultureProvider
                options.RequestCultureProviders.Insert(4, new AbpDefaultRequestCultureProvider());
                //5: AcceptLanguageHeaderRequestCultureProvider

                optionsAction?.Invoke(options);

                userProvider.CookieProvider = options.RequestCultureProviders.OfType<CookieRequestCultureProvider>().FirstOrDefault();
                userProvider.HeaderProvider = options.RequestCultureProviders.OfType<AbpLocalizationHeaderRequestCultureProvider>().FirstOrDefault();

                app.UseRequestLocalization(options);
            }
        }

        public static void UseAbpSecurityHeaders(this IApplicationBuilder app)
        {
            app.UseMiddleware<AbpSecurityHeadersMiddleware>();
        }
    }

  在这个方法中首先也是检查传入的IApplicationBuilder是否为null,如果为空则抛出异常,在检查完之后会创建一个AbpApplicationBuilderOptions类的实例,我们来看看在这个类中做了哪些事情?

 public AbpApplicationBuilderOptions()
        {
            UseCastleLoggerFactory = true;
            UseAbpRequestLocalization = true;
            UseSecurityHeaders = true;
        }

  这里比较简单就是对定义的几个属性进行初始化操作。在完成初始化操作后,首先就是定义ABP的创建Logger的工厂类,通过这个工厂类创建Logger的实例,这个主要是记录ABP的日志,这里面具体的日志使用的是log4net,具体输出日志的方式可以在log4net.config里面进行配置。

  在配置完成后最重要的一步就是执行InitializeAbp方法,我们来看看这个过程中执行了哪些方法。

private static void InitializeAbp(IApplicationBuilder app)
        {
            var abpBootstrapper = app.ApplicationServices.GetRequiredService<AbpBootstrapper>();
            abpBootstrapper.Initialize();

            var applicationLifetime = app.ApplicationServices.GetService<IApplicationLifetime>();
            applicationLifetime.ApplicationStopping.Register(() => abpBootstrapper.Dispose());
        }

  在这个初始化Abp方法中,首先就是通过app.ApplicationServices.GetRequiredService<AbpBootstrapper>()这个方法来获取到之前唯一的abpBootstrapper,获取到这个唯一的实例后就可以调用这个实例的Initialize方法。

 /// <summary>
        /// Initializes the ABP system.
        /// </summary>
        public virtual void Initialize()
        {
            ResolveLogger();

            try
            {
                RegisterBootstrapper();
                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;
            }
        }

  在整个初始化的过程中,第一步就是创建整个ABP中唯一的Logger对象,这个主要是用来记录系统的日志文件,这个具体创建方法就是通过IoCContainer容器来获取到之前注入的创建Logger日志的工厂类,然后调用它的Create方法来创建这个记录日志的对象。

 private void ResolveLogger()
        {
            if (IocManager.IsRegistered<ILoggerFactory>())
            {
                _logger = IocManager.Resolve<ILoggerFactory>().Create(typeof(AbpBootstrapper));
            }
        }

  在创建完日志之后,第一步就是用于判断当前的AbpBootrsrtapper类的实例有没有注入到整个依赖注入容器中,如果没有注入过则将当前唯一的实例this注入到容器中去。

private void RegisterBootstrapper()
        {
            if (!IocManager.IsRegistered<AbpBootstrapper>())
            {
                IocManager.IocContainer.Register(
                    Component.For<AbpBootstrapper>().Instance(this)
                    );
            }
        }

  再接下来第一步就是执行IocManager.IocContainer.Install(new AbpCoreInstaller())这一步操作,这一步的主要作用是注册系统框架级的所有配置类,我们通过实际的代码来看看,在初始化整个ABP系统时候到底注册了哪些系统框架级别的配置类。

internal class AbpCoreInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                Component.For<IUnitOfWorkDefaultOptions, UnitOfWorkDefaultOptions>().ImplementedBy<UnitOfWorkDefaultOptions>().LifestyleSingleton(),
                Component.For<INavigationConfiguration, NavigationConfiguration>().ImplementedBy<NavigationConfiguration>().LifestyleSingleton(),
                Component.For<ILocalizationConfiguration, LocalizationConfiguration>().ImplementedBy<LocalizationConfiguration>().LifestyleSingleton(),
                Component.For<IAuthorizationConfiguration, AuthorizationConfiguration>().ImplementedBy<AuthorizationConfiguration>().LifestyleSingleton(),
                Component.For<IValidationConfiguration, ValidationConfiguration>().ImplementedBy<ValidationConfiguration>().LifestyleSingleton(),
                Component.For<IFeatureConfiguration, FeatureConfiguration>().ImplementedBy<FeatureConfiguration>().LifestyleSingleton(),
                Component.For<ISettingsConfiguration, SettingsConfiguration>().ImplementedBy<SettingsConfiguration>().LifestyleSingleton(),
                Component.For<IModuleConfigurations, ModuleConfigurations>().ImplementedBy<ModuleConfigurations>().LifestyleSingleton(),
                Component.For<IEventBusConfiguration, EventBusConfiguration>().ImplementedBy<EventBusConfiguration>().LifestyleSingleton(),
                Component.For<IMultiTenancyConfig, MultiTenancyConfig>().ImplementedBy<MultiTenancyConfig>().LifestyleSingleton(),
                Component.For<ICachingConfiguration, CachingConfiguration>().ImplementedBy<CachingConfiguration>().LifestyleSingleton(),
                Component.For<IAuditingConfiguration, AuditingConfiguration>().ImplementedBy<AuditingConfiguration>().LifestyleSingleton(),
                Component.For<IBackgroundJobConfiguration, BackgroundJobConfiguration>().ImplementedBy<BackgroundJobConfiguration>().LifestyleSingleton(),
                Component.For<INotificationConfiguration, NotificationConfiguration>().ImplementedBy<NotificationConfiguration>().LifestyleSingleton(),
                Component.For<IEmbeddedResourcesConfiguration, EmbeddedResourcesConfiguration>().ImplementedBy<EmbeddedResourcesConfiguration>().LifestyleSingleton(),
                Component.For<IAbpStartupConfiguration, AbpStartupConfiguration>().ImplementedBy<AbpStartupConfiguration>().LifestyleSingleton(),
                Component.For<IEntityHistoryConfiguration, EntityHistoryConfiguration>().ImplementedBy<EntityHistoryConfiguration>().LifestyleSingleton(),
                Component.For<ITypeFinder, TypeFinder>().ImplementedBy<TypeFinder>().LifestyleSingleton(),
                Component.For<IAbpPlugInManager, AbpPlugInManager>().ImplementedBy<AbpPlugInManager>().LifestyleSingleton(),
                Component.For<IAbpModuleManager, AbpModuleManager>().ImplementedBy<AbpModuleManager>().LifestyleSingleton(),
                Component.For<IAssemblyFinder, AbpAssemblyFinder>().ImplementedBy<AbpAssemblyFinder>().LifestyleSingleton(),
                Component.For<ILocalizationManager, LocalizationManager>().ImplementedBy<LocalizationManager>().LifestyleSingleton()
                );
        }
    }

  这里面包括框架中各种重要的配置,比如实现整个框架插件化的核心管理类IAbpPlugInManager等等。在将这些核心的框架级别的配置类注入IoC容器中以后就是执行后续的各种操作了。首先第一步就是将放置在特定文件夹下面的实现AbpModule的程序集加载到一个唯一的集合中,这个具体是通过IocManager.Resolve<AbpPlugInManager>().PlugInSources.AddRange(PlugInSources)这个来实现的。

  紧接着就是执行IocManager.Resolve<AbpStartupConfiguration>().Initialize(),这个方法主要是用于实例化ABP系统中的各种配置,包括:本地化、模块、验证、多租户配置等一系列配置的初始化,这个在后期都会使用到。关于后面的这些内容,这个系列后续会通过不同章节来分析进行分析和总结。

  public void Initialize()
        {
            Localization = IocManager.Resolve<ILocalizationConfiguration>();
            Modules = IocManager.Resolve<IModuleConfigurations>();
            Features = IocManager.Resolve<IFeatureConfiguration>();
            Navigation = IocManager.Resolve<INavigationConfiguration>();
            Authorization = IocManager.Resolve<IAuthorizationConfiguration>();
            Validation = IocManager.Resolve<IValidationConfiguration>();
            Settings = IocManager.Resolve<ISettingsConfiguration>();
            UnitOfWork = IocManager.Resolve<IUnitOfWorkDefaultOptions>();
            EventBus = IocManager.Resolve<IEventBusConfiguration>();
            MultiTenancy = IocManager.Resolve<IMultiTenancyConfig>();
            Auditing = IocManager.Resolve<IAuditingConfiguration>();
            Caching = IocManager.Resolve<ICachingConfiguration>();
            BackgroundJobs = IocManager.Resolve<IBackgroundJobConfiguration>();
            Notifications = IocManager.Resolve<INotificationConfiguration>();
            EmbeddedResources = IocManager.Resolve<IEmbeddedResourcesConfiguration>();
            EntityHistory = IocManager.Resolve<IEntityHistoryConfiguration>();

            CustomConfigProviders = new List<ICustomConfigProvider>();
            ServiceReplaceActions = new Dictionary<Type, Action>();
        }

  在这后面就是整个ABP项目中的重中之重了就是关于各个Module的初始化,这里的主要步骤首先就是获取AbpModuleManager的实例,然后调用该对象的Initialize方法,在执行这个方法时会将整个ABP项目的启动Module(WebHostModule)作为TStartupModule参数传递进去,我们来看看在这个Initialize()方法中执行了哪些重要的事情。

 public virtual void Initialize(Type startupModule)
        {
            _modules = new AbpModuleCollection(startupModule);
            LoadAllModules();
        }

  在这个方法中,首先创建一个AbpModule的集合,然后就开始加载所有的Module了。

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);
        }

  在这个函数中,第一步就是找到所有的模块的类型,具体是通过FindAllModuleTypes这个函数来执行的,我们来看看到底是怎么实现的。

private List<Type> FindAllModuleTypes(out List<Type> plugInModuleTypes)
        {
            plugInModuleTypes = new List<Type>();

            var modules = AbpModule.FindDependedModuleTypesRecursivelyIncludingGivenModule(_modules.StartupModuleType);

            foreach (var plugInModuleType in _abpPlugInManager.PlugInSources.GetAllModules())
            {
                if (modules.AddIfNotContains(plugInModuleType))
                {
                    plugInModuleTypes.Add(plugInModuleType);
                }
            }

            return modules;
        }

  这里跳过一些步骤,直接看最核心的部分,执行到内部的一个AddModuleAndDependenciesRecursively方法,这个方法是一个迭代方法,在添加每一个Module时首先查找当前Module的依赖Module,如果当前Module已经添加到之前的集合中那么就不再重复添加。

 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);
            }
        }

 这里面有一个重点的方法FindDependedModuleTypes方法,我们也来看看其内部的实现。

/// <summary>
        /// Finds direct depended modules of a module (excluding given module).
        /// </summary>
        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;
        }

  在这个方法中我们首先判断当前类型当前moduleType是否定义了DependsOn的自定义属性,如果定义了这个这个自定义属性,那么首先获取定义的这些Module,然后再将这些ModuleType添加到一个集合中,这样就能够获取到一个ModuleType所依赖的所有其他ModuleType,通过上面的两个过程能够将整个ABP系统中 所有的AbpModule都加载到了一个集合中,而且不会重复。

  后面接着执行AbpModuleManager中的StartModules()方法,这个方法中会执行一系列的操作。

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());
        }

  分析到这里的时候我们可以看到我们非常熟悉的PreInitialze()、Initialize()、PostInitialize()方法了,在执行这三个虚方法之前,首先要将这些加载到的Module进行一个排序,具体排序规则我们称之为拓扑排序,就是如果A模块加载依赖于B模块,那么B模块就排在A模块的前面,并执行这三个过程。我们来分析一下GetSortedModuleListByDependency这个方法的具体实现。  

 public List<AbpModuleInfo> GetSortedModuleListByDependency()
        {
            var sortedModules = this.SortByDependencies(x => x.Dependencies);
            EnsureKernelModuleToBeFirst(sortedModules);
            EnsureStartupModuleToBeLast(sortedModules, StartupModuleType);
            return sortedModules;
        }

  在这里涉及到三类不同的模块,首先是AbpKenelModule,这个是Abp中最核心的Module、第二类就是普通的业务实现相关的Module、第三类是StartupModule,这个模块会最后进行加载,关于模块之间的先后排列顺序我们可以来通过几个资料来进行了解,首先我们来看看SortByDependencies这个方法的实现。

public static class ListExtensions
    {
        /// <summary>
        /// Sort a list by a topological sorting, which consider their  dependencies
        /// </summary>
        /// <typeparam name="T">The type of the members of values.</typeparam>
        /// <param name="source">A list of objects to sort</param>
        /// <param name="getDependencies">Function to resolve the dependencies</param>
        /// <returns></returns>
        public static List<T> SortByDependencies<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> getDependencies)
        {
            /* See: http://www.codeproject.com/Articles/869059/Topological-sorting-in-Csharp
             *      http://en.wikipedia.org/wiki/Topological_sorting
             */

            var sorted = new List<T>();
            var visited = new Dictionary<T, bool>();

            foreach (var item in source)
            {
                SortByDependenciesVisit(item, getDependencies, sorted, visited);
            }

            return sorted;
        }

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T">The type of the members of values.</typeparam>
        /// <param name="item">Item to resolve</param>
        /// <param name="getDependencies">Function to resolve the dependencies</param>
        /// <param name="sorted">List with the sortet items</param>
        /// <param name="visited">Dictionary with the visited items</param>
        private static void SortByDependenciesVisit<T>(T item, Func<T, IEnumerable<T>> getDependencies, List<T> sorted, Dictionary<T, bool> visited)
        {
            bool inProcess;
            var alreadyVisited = visited.TryGetValue(item, out inProcess);

            if (alreadyVisited)
            {
                if (inProcess)
                {
                    throw new ArgumentException("Cyclic dependency found! Item: " + item);
                }
            }
            else
            {
                visited[item] = true;

                var dependencies = getDependencies(item);
                if (dependencies != null)
                {
                    foreach (var dependency in dependencies)
                    {
                        SortByDependenciesVisit(dependency, getDependencies, sorted, visited);
                    }
                }

                visited[item] = false;
                sorted.Add(item);
            }
        }
    }

  除了代码注释中的这个URL涉及到的参考资料以外,可以点击这里参考这篇文章来进一步理解什么是拓扑排序规则。

  在这里我们已经基本分析完了整个UseAbp的过程,这个在整个方法中最核心的就是找到所有的Module并进行拓扑排序,排序完成后一次执行定义在基类中的虚方法,最后在UseAbp中涉及的一个部分就是本地化等相关的内容,这个不是整个ABP项目中的核心,但是对整个ABP项目是一个非常重要的补充,这里我们仅仅贴出实现代码,不做具体分析。  

 if (options.UseAbpRequestLocalization)
            {
                //TODO: This should be added later than authorization middleware!
                app.UseAbpRequestLocalization();
            }

            if (options.UseSecurityHeaders)
            {
                app.UseAbpSecurityHeaders();
            }

  这里面UseAbpRequestLocalization()这个方法的实现如下所示。

public static void UseAbpRequestLocalization(this IApplicationBuilder app, Action<RequestLocalizationOptions> optionsAction = null)
        {
            var iocResolver = app.ApplicationServices.GetRequiredService<IIocResolver>();
            using (var languageManager = iocResolver.ResolveAsDisposable<ILanguageManager>())
            {
                var supportedCultures = languageManager.Object
                    .GetLanguages()
                    .Select(l => CultureInfo.GetCultureInfo(l.Name))
                    .ToArray();

                var options = new RequestLocalizationOptions
                {
                    SupportedCultures = supportedCultures,
                    SupportedUICultures = supportedCultures
                };

                var userProvider = new AbpUserRequestCultureProvider();

                //0: QueryStringRequestCultureProvider
                options.RequestCultureProviders.Insert(1, userProvider);
                options.RequestCultureProviders.Insert(2, new AbpLocalizationHeaderRequestCultureProvider());
                //3: CookieRequestCultureProvider
                options.RequestCultureProviders.Insert(4, new AbpDefaultRequestCultureProvider());
                //5: AcceptLanguageHeaderRequestCultureProvider

                optionsAction?.Invoke(options);

                userProvider.CookieProvider = options.RequestCultureProviders.OfType<CookieRequestCultureProvider>().FirstOrDefault();
                userProvider.HeaderProvider = options.RequestCultureProviders.OfType<AbpLocalizationHeaderRequestCultureProvider>().FirstOrDefault();

                app.UseRequestLocalization(options);
            }
        }

  上面就是对整个ABP项目的模块加载及初始化过程做的一个主要的分析,但是在理解这篇文章之前,最好先看之前的一篇文章,从而让自己对整个ABP模块加载有一个更加清楚的认识和理解。

最后,点击这里返回整个ABP系列的主目录。



原文地址:https://www.cnblogs.com/seekdream/p/9537732.html

时间: 2024-08-30 03:42:13

ABP中模块初始化过程(二)的相关文章

Java中的初始化过程(转)

原文:http://www.cnblogs.com/mmbo/archive/2009/10/05/1578156.html 1.类成员自动初始化,基本类型总是最先初始化为0(boolean为false,(char)0),对象的引用初始化为null:2.类成员指定初始化,可以在类成员定义或构造器(包括其他方法)中给基本类型和非基本类型对象初始化,但这并不能阻止自动初始化首先进行:3.按类成员定义的顺序决定初始化的顺序:4.静态成员只有在第一次被访问时(class对象首次加载)才会被初始化,此后不

ABP中的模块初始化过程(一)

在总结完整个ABP项目的结构之后,我们就来看一看ABP中这些主要的模块是按照怎样的顺序进行加载的,在加载的过程中我们会一步步分析源代码来进行解释,从而使自己对于整个框架有一个清晰的脉络,在整个Asp.Net Core项目中,我们启动一个带Swagger UI的Web API项目为例,在介绍这个Web API项目之前我们先来看看整个Swagger 文档的样式. 我们定义的WebAPI最终都会以Swagger文档这种形式来展现出来,通过这种形式也是非常方便我们进行代码的调试的,在进行网站的前后端分离

Java中创建对象初始化过程的理解

以下面程序为例: 1.源码Cars.java通过编译生成Cars.class文件: 2.执行时分为两步: 第一步将Cars类的字节码加载到内存中, 第二步是new之后自动执行的.①将属性color和price初始化内存堆,并附上初始值null和0.0(声明,赋初值):②调用有两个参数的构造方法public Cars(String color,double price),把具体值"black"和60000赋值给形式参数color和price(即执行Cars("black&quo

Framebuffer 驱动学习总结(二)---- Framebuffer模块初始化

---恢复内容开始--- Framebuffer模块初始化过程:--driver\video\fbmem.c 1.  初始化Framebuffer: FrameBuffer驱动是以模块的形式注册到系统中,在模块初始化时,创建FrameBuffer对应的设备文件及proc文件,并注册FrameBuffer设备操作接口函数fb_fops. static int __init fbmem_init(void) { proc_create("fb", 0, NULL, &fb_proc

Nginx 中 HTTP模块初始化

概述 在前面的文章< Nginx 配置解析>简单讲解了通用模块的配置项解析,并且大概讲解了HTTP 模块的配置项解析过程,本文更具体的分析 HTTP 模块的初始化过程.HTTP 模块初始化过程主要有:上下文结构初始化.配置项解析.配置项合并.server 相关端口设置. HTTP 模块接口 ngx_http_module_t 结构体 在 Nginx 中,结构体 ngx_module_t 是 Nginx 模块最基本的接口.对于每一种不同类型的模块,都有一个具体的结构体来描述这一类模块的通用接口.

ABP中的拦截器之ValidationInterceptor(下)

在上篇我分析了整个ABP中ValitationInterceptor的整个过程,就其中涉及到的Validator过程没有详细的论述,这篇文章就这个过程进行详细的论述,另外任何一个重要的特性如何应用是最关键的部分,这篇文章就通过介绍具体的应用来说用到底在实际的项目中如何使用这些特性. 在上篇中我们知道MethodInvocationValidator中有一个重要的函数就是SetValidationErrors(validatingObject),这个过程就是查找ABP中的所有Validator类型

[转]在static代码块或static变量的初始化过程中使用ServiceManager提供的api的陷阱

一. 案例 1.源码: /** @hide */ private TelephonyManager(int slotId) { mContext = null; mSlotId = slotId; if (sRegistry == null) { if (sRegistry == null) { sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( "telephony.registry")

Win32中GDI+应用(二)--初始化与清理

GDI+提供了GdiplusStartup和 GdiplusShutdown 函数来进行初始化和完成清理工作.你必须在调用其他的GDI+函数之前,调用GdiplusStartup函数,在完成GDI+工作后调用GdiplusShutdown .具体的可以看下面的MSDN上的例子: #include <windows.h> #include <gdiplus.h> #include <stdio.h> using namespace Gdiplus; int main()

java中对象的初始化过程

class Parent{ int num = 8;// ->3 Parent(){ //super(); // ->2 //显示初始化 // ->3 //构造代码段 // ->4 show(); // ->5 } {// ->4 System.out.println("Parent constructor code run->"); } public void show(){//被覆盖 System.out.println("num