3-dubbo框架,应用程序,模块领域模型Model对象的初始化

news2024/12/23 16:00:51

在上一章中我们详细看了服务配置ServiceConfig类型的初始化,不过我们跳过了AbstractMethodConfig的构造器中创建模块模型对象的过程

那为什么会在Dubbo3的新版本中加入这个域模型呢,主要有如下原因
之前dubbo都是只有一个作用域的,通过静态类 属性共享
增加域模型是为了:

1.让Dubbo支持多应用的部署,这块一些大企业有诉求
2.从架构设计上,解决静态属性资源共享、清理的问题
3.分层模型将应用的管理和服务的管理分开
可能比较抽象,可以具体点来开Dubbo3中在启动时候需要启动配置中心,元数据中心
这个配置中心和元数据中心可以归应用模型来管理,Dubbo作为RPC框架有需要启动服务和引用服务,服务级别的管理就交给了这个模块模型来管理,分层次的管理方便我们理解和处理逻辑,父子级别的模型又方便了数据传递。

了解过JVM类加载机制的同学应该就比较清楚 JVM类加载过程中的数据访问模型,子类加载器先去父类加载器去找不到则从子类型加载器中查找类型,Dubbo的分层模型类似这样一种机制,这一章先来简单了解下后面用到时候具体细说。

模型对象的关系

在这里插入图片描述
看最新图

模型对象一共有4个,公共的属性和操作放在了域模型类型中,下面我们来详细说下这几个模型类型:

  • ExtensionAccessor 扩展的统一访问器

    • 用于获取扩展加载管理器ExtensionDirector对象
    • 获取扩展对象ExtensionLoader
    • 根据扩展名字获取具体扩展对象
    • 获取自适应扩展对象
    • 获取默认扩展对象
  • ScopeModel 模型对象的公共抽象父类型

    • 内部id用于表示模型树的层次结构
    • 公共模型名称,可以被用户设置
    • 描述信息
    • 类加载器管理
    • 父模型管理parent
    • 当前模型的所属域ExtensionScope有:FRAMEWORK(框架),APPLICATION(应用),MODULE(模块),SELF(自给自足,为每个作用域创建一个实例,用于特殊的SPI扩展,如ExtensionInjector)
    • 具体的扩展加载程序管理器对象的管理:ExtensionDirector
    • 域Bean工厂管理,一个内部共享的Bean工厂ScopeBeanFactory
  • FrameworkModel dubbo框架模型,可与多个应用程序共享

    • FrameworkModel实例对象集合,allInstances
    • 所有ApplicationModel实例对象集合,applicationModels
    • 发布的ApplicationModel实例对象集合pubApplicationModels
    • 框架的服务存储库FrameworkServiceRepository类型对象(数据存储在内存中)
    • 内部的应用程序模型对象internalApplicationModel
  • ApplicationModel 表示正在使用Dubbo的应用程序,并存储基本元数据信息,以便在RPC调用过程中使用。ApplicationModel包括许多关于发布服务的ProviderModel和许多关于订阅服务的Consumer Model。

    • ExtensionLoader、DubboBootstrap和这个类目前被设计为单例或静态(本身完全静态或使用一些静态字段)。因此,从它们返回的实例属于流程范围。如果想在一个进程中支持多个dubbo服务器,可能需要重构这三个类。
    • 所有ModuleModel实例对象集合moduleModels
    • 发布的ModuleModel实例对象集合pubModuleModels
    • 环境信息Environment实例对象environment
    • 配置管理ConfigManager实例对象configManager
    • 服务存储库ServiceRepository实例对象serviceRepository
    • 应用程序部署器ApplicationDeployer实例对象deployer
    • 所属框架FrameworkModel实例对象frameworkModel
    • 内部的模块模型ModuleModel实例对象internalModule
    • 默认的模块模型ModuleModel实例对象defaultModule
  • ModuleModel 服务模块的模型

    • 所属应用程序模型ApplicationModel实例对象applicationModel
    • 模块环境信息ModuleEnvironment实例对象moduleEnvironment
    • 模块服务存储库ModuleServiceRepository实例对象serviceRepository
    • 模块的服务配置管理ModuleConfigManager实例对象moduleConfigManager
    • 模块部署器ModuleDeployer实例对象deployer用于导出和引用服务

了解了这几个模型对象的关系我们可以了解到这几个模型对象的管理层级从框架到应用程序,然后到模块的管理(FrameworkModel->ApplicationModel->ModuleModel),他们主要用来针对框架,应用程序,模块的存储,发布管理,配置管理

ApplicationModel.defaultModel().getDefaultModule()

我们分析这一行做了哪些事情

使用双重校验锁获取框架模型对象

/**
     * During destroying the default FrameworkModel, the FrameworkModel.defaultModel() or ApplicationModel.defaultModel()
     * will return a broken model, maybe cause unpredictable problem.
     * Recommendation: Avoid using the default model as much as possible.
     * @return the global default FrameworkModel
     *
     *  在源码的注释上有这么一句话:在销毁默认的 FrameworkModel 时, FrameworkModel.defaultModel()
     *     *或ApplicationModel.defaultModel() 将返回一个损坏的模型
     *     *可能会导致不可预知的问题。建议:尽量避免使用默认模型。
     */
    public static FrameworkModel defaultModel() {
        FrameworkModel instance = defaultInstance;
        if (instance == null) {
            synchronized (globalLock) {
                resetDefaultFrameworkModel();
                if (defaultInstance == null) {
                    defaultInstance = new FrameworkModel();
                }
                instance = defaultInstance;
            }
        }
        Assert.notNull(instance, "Default FrameworkModel is null");
        return instance;
    }

创建FrameworkModel对象

public FrameworkModel() {
        super(null, ExtensionScope.FRAMEWORK, false);
        synchronized (globalLock) {
            synchronized (instLock) {
                /**
                 * 内部id用于表示模型树的层次结构,如层次结构:
                 * FrameworkModel(索引=1)->ApplicationModel(索引=2)->ModuleModel(索引=1,第一个用户模块)
                 * 这个index变量是static类型的为静态全局变量默认值从1开始,如果有多个框架模型对象则internalId编号从1开始依次递增
                 */
                this.setInternalId(String.valueOf(index.getAndIncrement()));
                // register FrameworkModel instance early
                allInstances.add(this);
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info(getDesc() + " is created");
                }
                initialize();

                TypeDefinitionBuilder.initBuilders(this);

                serviceRepository = new FrameworkServiceRepository(this);

                //Initializer 初始化程序 框架自身提供的一个扩展类
                //获取ScopeModelInitializer类型(域模型初始化器)的扩展加载器ExtensionLoader,
                // 每个扩展类型都会创建一个扩展加载器缓存起来
                ExtensionLoader<ScopeModelInitializer> initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class);
                //获取ScopeModelInitializer类型的支持的扩展集合,这里当前版本存在10个扩展类型实现
                Set<ScopeModelInitializer> initializers = initializerExtensionLoader.getSupportedExtensionInstances();
                //遍历这些扩展实现调用他们的initializeFrameworkModel方法来传递FrameworkModel类型对象,细节我们待会再详细说下
                for (ScopeModelInitializer initializer : initializers) {
                    initializer.initializeFrameworkModel(this);
                }
                //创建一个内部的ApplicationModel类型,细节下面说
                internalApplicationModel = new ApplicationModel(this, true);
                //创建ApplicationConfig类型对象同时传递应用程序模型对象internalApplicationModel
                //获取ConfigManager类型对象,然后设置添加当前应用配置对象
                internalApplicationModel.getApplicationConfigManager().setApplication(
                    new ApplicationConfig(internalApplicationModel, CommonConstants.DUBBO_INTERNAL_APPLICATION));
                internalApplicationModel.setModelName(CommonConstants.DUBBO_INTERNAL_APPLICATION);
            }
        }
    }

ScopeModelInitializer 历史dubbo的spi机制,目前实现了10个实现类,FrameworkModel,ApplicationModel 和 ModuleModel,调用不同的初始化方法,完成不同Model的初始化工作,其实都是注册到BeanFactory中一些bean
在这里插入图片描述

初始类型定义构建器

 TypeDefinitionBuilder.initBuilders(this);
 public static void initBuilders(FrameworkModel model) {
        Set<TypeBuilder> tbs = model.getExtensionLoader(TypeBuilder.class).getSupportedExtensionInstances();
        BUILDERS = new ArrayList<>(tbs);
    }

服务存储仓库对象的创建

public FrameworkServiceRepository(FrameworkModel frameworkModel) {
        this.frameworkModel = frameworkModel;
    }

初始化FrameworkModel

这一部分是在ScopeModel中进行的, 无论是FrameworkModel,还是ApplicationModel 和 ModuleModel 都是一样的

protected void initialize() {
        synchronized (instLock) {
            /**
             * 初始化ExtensionDirector是一个作用域扩展加载程序管理器。
             * ExtensionDirector支持多个级别,子级可以继承父级的扩展实例。
             * 查找和创建扩展实例的方法类似于Java classloader。
             */
            this.extensionDirector = new ExtensionDirector(parent != null ? parent.getExtensionDirector() : null, scope, this);
            ///这个参考了Spring的生命周期回调思想,添加一个扩展初始化的前后调用的处理器,
            // 在扩展初始化之前或之后调用的后处理器,参数类型为ExtensionPostProcessor
            this.extensionDirector.addExtensionPostProcessor(new ScopeModelAwareExtensionProcessor(this));
            //创建一个内部共享的域工厂对象,用于注册Bean,创建Bean,获取Bean,初始化Bean等
            this.beanFactory = new ScopeBeanFactory(parent != null ? parent.getBeanFactory() : null, extensionDirector);

            // Add Framework's ClassLoader by default
            // 将当前类的加载器存入加载器集合classLoaders中
            ClassLoader dubboClassLoader = ScopeModel.class.getClassLoader();
            if (dubboClassLoader != null) {
                this.addClassLoader(dubboClassLoader);
            }
        }
    }

创建ApplicationModel对象

public ApplicationModel defaultApplication() {
        ApplicationModel appModel = this.defaultAppModel;
        if (appModel == null) {
            // check destroyed before acquire inst lock, avoid blocking during destroying
            checkDestroyed();
            resetDefaultAppModel();
            if ((appModel = this.defaultAppModel) == null) {
                synchronized (instLock) {
                    if (this.defaultAppModel == null) {
                        this.defaultAppModel = newApplication();
                    }
                    appModel = this.defaultAppModel;
                }
            }
        }
        Assert.notNull(appModel, "Default ApplicationModel is null");
        return appModel;
    }

构造方法

 protected ApplicationModel(FrameworkModel frameworkModel) {
        this(frameworkModel, false);
    }
    
    protected ApplicationModel(FrameworkModel frameworkModel, boolean isInternal) {
        super(frameworkModel, ExtensionScope.APPLICATION, isInternal);
        synchronized (instLock) {
            Assert.notNull(frameworkModel, "FrameworkModel can not be null");
            this.frameworkModel = frameworkModel;
            //frameworkMode 添加 applicationModel
            frameworkModel.addApplication(this);
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info(getDesc() + " is created");
            }
            initialize();
            //创建一个内部的模块模型对象
            this.internalModule = new ModuleModel(this, true);
            //创建一个独立服务存储对象
            this.serviceRepository = new ServiceRepository(this);

            //获取应用程序初始化监听器ApplicationInitListener扩展
            ExtensionLoader<ApplicationInitListener> extensionLoader = this.getExtensionLoader(ApplicationInitListener.class);
            //如果存在应用程序初始化监听器扩展则执行这个初始化方法,在当前的版本还未看到有具体的扩展实现类型
            Set<String> listenerNames = extensionLoader.getSupportedExtensions();
            for (String listenerName : listenerNames) {
                extensionLoader.getExtension(listenerName).init();
            }
            //初始化扩展(这个是应用程序生命周期的方法调用,这里调用初始化方法
            initApplicationExts();

            //获取域模型初始化器扩展对象列表,然后执行初始化方法
            ExtensionLoader<ScopeModelInitializer> initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class);
            Set<ScopeModelInitializer> initializers = initializerExtensionLoader.getSupportedExtensionInstances();
            for (ScopeModelInitializer initializer : initializers) {
                initializer.initializeApplicationModel(this);
            }

            Assert.notNull(getApplicationServiceRepository(), "ApplicationServiceRepository can not be null");
            Assert.notNull(getApplicationConfigManager(), "ApplicationConfigManager can not be null");
            Assert.assertTrue(getApplicationConfigManager().isInitialized(), "ApplicationConfigManager can not be initialized");
        }
    }

将ApplicationModel添加至FrameworkModel容器中

void addApplication(ApplicationModel applicationModel) {
        // can not add new application if it's destroying
        checkDestroyed();
        synchronized (instLock) {
            if (!this.applicationModels.contains(applicationModel)) {
                applicationModel.setInternalId(buildInternalId(getInternalId(), appIndex.getAndIncrement()));
                this.applicationModels.add(applicationModel);
                if (!applicationModel.isInternal()) {
                    //如果非内部的则也向公开应用模型集合pubApplicationModels中添加一下
                    this.pubApplicationModels.add(applicationModel);
                }
            }
        }
    }

三者的序列号生成

 protected String buildInternalId(String parentInternalId, long childIndex) {
        // FrameworkModel    1
        // ApplicationModel  1.1
        // ModuleModel       1.1.1
        if (StringUtils.hasText(parentInternalId)) {
            return parentInternalId + "." + childIndex;
        } else {
            return "" + childIndex;
        }
    }

调用父类的初始化

和FrameModel一样不再详细说明

initApplicationExts() 初始化应用程序扩展方法

这里目前是Environment 和 ConfigManger类实现, Enviroment 是应用环境相关信息,后面单独写一章
在这里插入图片描述

 //初始化扩展(这个是应用程序生命周期的方法调用,这里调用初始化方法
            initApplicationExts();
// already synchronized in constructor
    private void initApplicationExts() {
        //这个扩展实现一共有两个可以看下面那个图扩展类型为ConfigManager和Environment
        Set<ApplicationExt> exts = this.getExtensionLoader(ApplicationExt.class).getSupportedExtensionInstances();
        for (ApplicationExt ext : exts) {
            ext.initialize();
        }
    }

ConfigManager类型的initialize方法

先简单说下ConfigManager的作用,无锁配置管理器(通过ConcurrentHashMap),用于快速读取操作。写入操作锁带有配置类型的子配置映射,用于安全检查和添加新配置。其实ConfigManager实现类中并没有这个初始化方法initialize,不过ConfigManager的父类型AbstractConfigManager中是有initialize方法的,如下所示:

 @Override
    public void initialize() throws IllegalStateException {
        if (!initialized.compareAndSet(false, true)) {
            return;
        }
        //从模块环境中获取组合配置,目前Environment中有6种重要的配置,我们后面详细说
        CompositeConfiguration configuration = scopeModel.getModelEnvironment().getConfiguration();

        // dubbo.config.mode
        // dubbo.config.mode获取配置模式,配置模式对应枚举类型ConfigMode,
        // 目前有这么几个STRICT,OVERRIDE,OVERRIDE_ALL,OVERRIDE_IF_ABSENT,IGNORE,
        // 这个配置决定了属性覆盖的顺序,当有同一个配置key多次出现时候,以最新配置为准,
        // 还是以最老的那个配置为准,还是配置重复则抛出异常,默认值为严格模式STRICT重复则抛出异常
        String configModeStr = (String) configuration.getProperty(ConfigKeys.DUBBO_CONFIG_MODE);
        try {
            if (StringUtils.hasText(configModeStr)) {
                this.configMode = ConfigMode.valueOf(configModeStr.toUpperCase());
            }
        } catch (Exception e) {
            String msg = "Illegal '" + ConfigKeys.DUBBO_CONFIG_MODE + "' config value [" + configModeStr + "], available values " + Arrays.toString(ConfigMode.values());
            logger.error(COMMON_PROPERTY_TYPE_MISMATCH, "", "", msg, e);
            throw new IllegalArgumentException(msg, e);
        }

        // dubbo.config.ignore-duplicated-interface
        String ignoreDuplicatedInterfaceStr = (String) configuration
                .getProperty(ConfigKeys.DUBBO_CONFIG_IGNORE_DUPLICATED_INTERFACE);
        if (ignoreDuplicatedInterfaceStr != null) {
            this.ignoreDuplicatedInterface = Boolean.parseBoolean(ignoreDuplicatedInterfaceStr);
        }

        // print
        Map<String, Object> map = new LinkedHashMap<>();
        map.put(ConfigKeys.DUBBO_CONFIG_MODE, configMode);
        map.put(ConfigKeys.DUBBO_CONFIG_IGNORE_DUPLICATED_INTERFACE, this.ignoreDuplicatedInterface);
        logger.info("Config settings: " + map);
    }

Environment类型的initialize方法

这是一个与环境配置有关系的类型,我们先来简单了解下它的初始化方法,后期再详细说明:
Environment类型的initialize方法

@Override
    public void initialize() throws IllegalStateException {
        if (initialized.compareAndSet(false, true)) {
            //PropertiesConfiguration从系统属性和dubbo.properties中获取配置
            this.propertiesConfiguration = new PropertiesConfiguration(scopeModel);
            //SystemConfiguration获取的是JVM参数 启动命令中-D指定的
            this.systemConfiguration = new SystemConfiguration();
            //EnvironmentConfiguration是从环境变量中获取的配置
            this.environmentConfiguration = new EnvironmentConfiguration();
            //外部的Global配置config-center global/default config
            this.externalConfiguration = new InmemoryConfiguration("ExternalConfig");
            //外部的应用配置如:config-center中的应用配置
            this.appExternalConfiguration = new InmemoryConfiguration("AppExternalConfig");
            //本地应用配置 , 如Spring Environment/PropertySources/application.properties
            this.appConfiguration = new InmemoryConfiguration("AppConfig");
            //服务迁移配置加载 dubbo2升级dubbo3的一些配置
            loadMigrationRule();
        }
    }
 /**
     * @deprecated MigrationRule will be removed in 3.1
     * //服务迁移配置加载 JVM  > env >  代码路径dubbo-migration.yaml
     */
    @Deprecated
    private void loadMigrationRule() {
        if (Boolean.parseBoolean(System.getProperty(CommonConstants.DUBBO_MIGRATION_FILE_ENABLE, "false"))) {
            //文件路径配置的key dubbo.migration.file
            // JVM参数中获取
            String path = System.getProperty(CommonConstants.DUBBO_MIGRATION_KEY);
            if (StringUtils.isEmpty(path)) {
                //env环境变量中获取
                path = System.getenv(CommonConstants.DUBBO_MIGRATION_KEY);
                if (StringUtils.isEmpty(path)) {
                    //类路径下获取文件dubbo-migration.yaml
                    path = CommonConstants.DEFAULT_DUBBO_MIGRATION_FILE;
                }
            }
            this.localMigrationRule = ConfigUtils.loadMigrationRule(scopeModel.getClassLoaders(), path);
        } else {
            this.localMigrationRule = null;
        }
    }

创建ModuleModel对象

 protected ModuleModel(ApplicationModel applicationModel, boolean isInternal) {
        super(applicationModel, ExtensionScope.MODULE, isInternal);
        synchronized (instLock) {
            Assert.notNull(applicationModel, "ApplicationModel can not be null");
            this.applicationModel = applicationModel;
            applicationModel.addModule(this, isInternal);
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info(getDesc() + " is created");
            }

            initialize();

            this.serviceRepository = new ModuleServiceRepository(this);

            initModuleExt();

            ExtensionLoader<ScopeModelInitializer> initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class);
            Set<ScopeModelInitializer> initializers = initializerExtensionLoader.getSupportedExtensionInstances();
            for (ScopeModelInitializer initializer : initializers) {
                initializer.initializeModuleModel(this);
            }
            Assert.notNull(getServiceRepository(), "ModuleServiceRepository can not be null");
            Assert.notNull(getConfigManager(), "ModuleConfigManager can not be null");
            Assert.assertTrue(getConfigManager().isInitialized(), "ModuleConfigManager can not be initialized");

            // notify application check state
            // 获取应用程序发布对象,通知检查状态
            ApplicationDeployer applicationDeployer = applicationModel.getDeployer();
            if (applicationDeployer != null) {
                applicationDeployer.notifyModuleChanged(this, DeployState.PENDING);
            }
        }
    }

将模块模型添加至应用模型中


    void addModule(ModuleModel moduleModel, boolean isInternal) {
        synchronized (instLock) {
            if (!this.moduleModels.contains(moduleModel)) {
                checkDestroyed();
                this.moduleModels.add(moduleModel);
                //设置模块模型内部id,这个内部id生成过程与上面将应用模型添加到框架模型中的方式是一致的
                //可以参考 3.3.2 将ApplicationModel添加至FrameworkModel容器中
                moduleModel.setInternalId(buildInternalId(getInternalId(), moduleIndex.getAndIncrement()));
                if (!isInternal) {
                    //如果不是内部模型则添加到公开模块模型中
                    pubModuleModels.add(moduleModel);
                }
            }
        }
    }

初始化

调用父类的

模块服务存储库的创建

ModuleServiceRepository存储库中使用框架存储库frameworkServiceRepository来间接存储
这里我们看下怎么通过模块模型获取框架服务存储库frameworkServiceRepository:通过代码

public ModuleServiceRepository(ModuleModel moduleModel) {
        this.moduleModel = moduleModel;
        frameworkServiceRepository = ScopeModelUtil.getFrameworkModel(moduleModel).getServiceRepository();
    }

    public static FrameworkModel getFrameworkModel(ScopeModel scopeModel) {
        if (scopeModel == null) {
            return FrameworkModel.defaultModel();
        }
        //通过成员变量获取(构造器初始化的时候将FrameworkModel赋值给了ApplicationModel的成员变量
        if (scopeModel instanceof ApplicationModel) {
            return ((ApplicationModel) scopeModel).getFrameworkModel();
        } else if (scopeModel instanceof ModuleModel) {
            ModuleModel moduleModel = (ModuleModel) scopeModel;
            //间接通过ApplicationModel获取,不越级获取、
            return moduleModel.getApplicationModel().getFrameworkModel();
        } else if (scopeModel instanceof FrameworkModel) {
            return (FrameworkModel) scopeModel;
        } else {
            throw new IllegalArgumentException("Unable to get FrameworkModel from " + scopeModel);
        }
    }

当scopeModel instanceof ModuleModel 时返回的是FrameworkModel

模块配置管理器对象的创建与初始化

代码比较简单 看一下uml结构吧
在这里插入图片描述

@Override
    public void initialize() throws IllegalStateException {
        if (initialized.compareAndSet(false, true)) {
            this.orderedPropertiesConfiguration = new OrderedPropertiesConfiguration(moduleModel);
        }
    }

####。OrderedPropertiesConfiguration对象的创建

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/661500.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MacBook充电限制工具AlDente Pro

AlDente Pro是一款适用于Mac操作系统的小工具&#xff0c;可以帮助您限制电池充电量以延长电池寿命。通常情况下&#xff0c;电池在充满的状态下会继续接受电源充电&#xff0c;这可能会导致电池寿命缩短。使用AlDente Pro&#xff0c;您可以设置电池只充到特定的充电水平&…

使用omp并行技术实现快排加速

快排基本原理&#xff1a; 快速排序可以说是最为常见的排序算法&#xff0c;冒泡排序时间复杂度达到了O&#xff08;N2&#xff09;&#xff0c;而桶排序容易造成浪费空间。快排&#xff08;Quicksort&#xff09;就成为了不错的选择。 1、原理&#xff1a;快排需要找一个数作…

【Nexus】上传jar至Nexus的两种方式

目录 一、前言二、pom文件添加推送代码配置1、配置pom.xml文件2、配置maven的settings.xml文件3、执行上传①、点击Maven-Lifecycle-deploy-Run Maven Build②、出现以下提示则上传成功③、这时&#xff0c;在Nexus的nexus-snapshot-hosted&#xff08;快照类型的托管资源库&am…

【Python】函数进阶 ③ ( 函数作为参数传递 )

文章目录 一、函数参数传递类型二、代码示例 - 函数参数传递类型 一、函数参数传递类型 之前介绍的函数 , 都是 接收具体的 变量 或 字面量 数据 作为参数 , 如 : 数字 / 布尔值 / 字典 / 列表 / 元组 等 ; 函数 也可以作为参数 , 传入另一个函数中 ; 在 Python 中&#xff0…

主成分分析——SPSS实例分析

主成分分析是用原始变量的线性组合来表示主成分&#xff0c;且主成分彼此之间互不相关&#xff0c;且能反映出原始数据的绝大部分信息。 一般来说&#xff0c;当研究的问题涉及到多变量且变量之间存在很强的相关性时&#xff0c;我们可考虑使用主成分分析的方法来对数据进行简化…

智能的突破或许在智能之外

人工智能已经取得了不少令人瞩目的成果&#xff0c;但是仍然存在着许多问题和挑战&#xff0c;这些问题和挑战也许只能通过跨学科的合作和人类的智慧来解决&#xff0c;因此智能的突破在智能之外。在人工智能的决策过程中&#xff0c;往往会缺乏人类的道德判断和社会责任感&…

2018年全国硕士研究生入学统一考试管理类专业学位联考英语(二)试题

2018 年全国硕士研究生入学统一考试 管理类专业硕士学位联考 英语&#xff08;二&#xff09;试卷 考生须知 1&#xff0e;考生必须严格遵守各项考场规则。 2&#xff0e;答题前&#xff0c;考生将答题卡上的“姓名”、“考生编号”等信息填写清楚&#xff0c;并与准考证上的致…

【SpringCloud】Eureka 案例上手稍微带点原理

文章目录 1. 前置工作1.1 搭建 user-server1.1.1 pom1.1.2 po&#xff0c;mapper&#xff0c;controller1.1.3 yml1.1.4 启动类1.1.5 启动并访问 1.2 搭建 order-server1.2.1 pom1.2.2 po mapper controller1.2.3 yml1.2.4 启动类1.2.5 启动并访问 1.3 两个服务通信 2. Eureka2…

Qt Xml的读、写、修改、删除

一、说明 Xml文件的创建、读取、修改、删除以下图格式为例。 二、导入xml QT core gui xml三、创建Xml void MainWindow::Xml_Write(QString path) {//! 打开或创建文件QFile file(path);if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return; //! …

【MySQL篇】Select语句原理详解

文章目录 MYSQL体系结构模块详解架构分层连接层服务层存储引擎 SQL的执行流程连接查询缓存语法解析和预处理词法解析语法分析预处理器 查询优化器执行计划存储引擎存储引擎基本介绍如何选择存储引擎&#xff1f; 执行引擎举例说明 对于一个开发工程师来说&#xff0c;了解一下 …

C语言读写ini配置文件

环境 windows 10 64bitClion 2023.1 ini简介 ini 文件格式是一种用于保存配置信息的简单文本格式。它通常由多个节(section)组成&#xff0c;每个节包含多个键值对(key-value pair)。 下面是 ini 文件的基本语法规则 一个ini文件由多个节组成&#xff0c;每个节用方括号([])括起…

《Java黑皮书基础篇第10版》 第17章【笔记】

第十七章 二进制I/O 17.1 引言 文件可以不严谨的分类为文本文件和二进制文件。文本文件指的是可以用文件编辑器进行查看和修改的&#xff0c;二进制文件则不可以使用文本编辑器查看和修改。 例如&#xff0c;Test.java文件储存在文本文件中&#xff0c;因此可以用文本编辑器…

MapReduce程序基本架构

MapReduce程序是以&#xff08;键/值&#xff09;对的形式来处理数据的&#xff0c;即可以通过以下的形式来表示&#xff1a; map: (K1,V1) ➞ list(K2,V2) reduce: (K2,list(V2)) ➞ list(K3,V3) 不令人惊奇的是&#xff0c;这是一种超越一般数据的数据流表示形式。在本文中…

使用PyMC进行时间序列分层建模

在统计建模领域&#xff0c;理解总体趋势的同时解释群体差异的一个强大方法是分层(或多层)建模。这种方法允许参数随组而变化&#xff0c;并捕获组内和组间的变化。在时间序列数据中&#xff0c;这些特定于组的参数可以表示不同组随时间的不同模式。 今天&#xff0c;我们将深…

ood的5C解题法(1)----管理类面试对象设计

管理类 概念 可以模拟/代替管理员日常工作的系统 下面用停车场系统做演示 答题流程 Clarify What&#xff1a;除题目中的名词外&#xff0c;从管理的名词考虑 parking lot是什么类型的&#xff1f;如果楼有多层&#xff0c;停车位也是多层&#xff0c;则parking lot->pa…

Windows Server 2019 OVF, updated Jun 2023 (sysin) - VMware 虚拟机模板

Windows Server 2019 OVF, updated Jun 2023 (sysin) - VMware 虚拟机模板 2023 年 6 月版本更新&#xff0c;现在自动运行 sysprep&#xff0c;支持 ESXi Host Client 部署 请访问原文链接&#xff1a;https://sysin.org/blog/windows-server-2019-ovf/&#xff0c;查看最新…

5、产品经理的工作职责OR主要工作技能和工具

1、产品经理的工作职责 我们通过一个案例来了解产品经理的工作职责。 老板让你给他点餐&#xff0c;你应该怎么做&#xff1f;你需要考虑哪一些方面的问题&#xff1f; 例如&#xff1a;你预算多少&#xff0c;预算是十块钱还是100块还是1000块。有没有忌口&#xff0c;口味…

【MYSQL篇】Update语句原理详解

文章目录 前言缓冲池Buffer PoolInnoDB 内存结构redo logundo logBinlog 总结 前言 前面的文章我们已经对MySQL的查询语句的执行流程进行了说明&#xff0c;感兴趣的可以去看看&#xff1a; 【MySQL篇】Select语句原理详解 本篇文章我们来聊聊 MySQL更新语句的执行原理。更新…

Win7系统提示Windows Defender无法扫描选定的文件解决方法

Win7 64位系统提示“Windows Defender无法扫描选定的文件”怎么办呢?使用Windows Defender扫描文件,结果弹出如下图窗口,该怎么解决呢,参考下文,一起来解决Win7系统提示“Windows Defender无法扫描选定的文件”的解决方法。 原因分析: 这是因为开启Defender扫描压…

java的序列化注解Serial、序列化版本号serialVersionUID

例如&#xff0c;jdk源码NTLMException类的定义&#xff0c;其中涉及到了序列化注解Serial和序列化版本号字段serialVersionUID&#xff1a; 序列化注解java.io.Serial&#xff1a; 序列化注解java.io.Serial是在javaSE-14版本引入的。通常注解实现了序列化类的序列化相关的函…