当前位置: 首页 > news >正文

发布订阅者=>fiber=>虚拟dom

文章目录

    • vue的响应式原理-发布订阅者模式
    • vue3 响应式原理及优化
    • fiber
    • fiber 与 虚拟dom

vue的响应式原理-发布订阅者模式

  1. Vue响应式原理概述
    • Vue.js的响应式原理是其核心特性之一。它使得当数据发生变化时,与之绑定的DOM元素能够自动更新。其主要基于数据劫持和发布 - 订阅模式(也有观察者模式的概念在里面)来实现。
  2. 数据劫持
    • 概念:数据劫持是指在访问或者修改对象的属性时,通过一些方法拦截这个操作,添加自己的处理逻辑。在Vue中,主要是通过Object.defineProperty()方法来实现数据劫持。
    • 示例
      let data = {name: 'John'
      };
      let value;
      Object.defineProperty(data, 'name', {get() {console.log('获取name属性');return value;},set(newValue) {console.log('设置name属性');value = newValue;}
      });
      console.log(data.name);
      data.name = 'Jane';
      
    • 在这个例子中,当读取data.name时,会触发get方法,当修改data.name时,会触发set方法。这样就可以在获取和设置属性的时候添加自己的逻辑,比如在set方法中可以通知相关的依赖进行更新。
  3. 发布 - 订阅者模式(观察者模式)
    • 概念
      • 发布 - 订阅模式:包含发布者和订阅者。发布者发布消息,订阅者订阅消息,当发布者发布消息时,所有订阅该消息的订阅者都会收到通知并执行相应的操作。
      • 观察者模式:和发布 - 订阅模式类似,主要区别在于观察者模式中,被观察的对象(目标对象)直接维护一组观察者对象,当自身状态改变时,直接通知观察者。而发布 - 订阅模式有一个中间的消息队列或者事件中心来管理消息的发布和订阅。在Vue的响应式原理中,这两种模式的概念都有涉及。
    • 示例(简单的发布 - 订阅模式实现)
      class EventEmitter {constructor() {this.events = {};}on(eventName, callback) {if (!this.events[eventName]) {this.events[eventName] = [];}this.events[eventName].push(callback);}emit(eventName, data) {if (this.events[eventName]) {this.events[eventName].forEach(callback => {callback(data);});}}
      }
      let emitter = new EventEmitter();
      function callback1(data) {console.log('订阅者1收到消息:', data);
      }
      function callback2(data) {console.log('订阅者2收到消息:', data);
      }
      emitter.on('message', callback1);
      emitter.on('message', callback2);
      emitter.emit('message', 'Hello, World!');
      
      • 在这个例子中,EventEmitter是发布 - 订阅模式的核心类。on方法用于订阅消息,emit方法用于发布消息。当发布message消息时,订阅了message消息的callback1callback2函数都会被执行。
  4. Vue中响应式原理的实现步骤
    • 数据观察(数据劫持)
      • Vue会遍历数据对象的所有属性。对于每个属性,使用Object.defineProperty()进行数据劫持,设置getset方法。在get方法中,收集依赖(将当前的Watcher添加到依赖列表中),在set方法中,当属性值发生变化时,通知所有依赖(通过发布 - 订阅模式,通知订阅了该属性变化的Watcher)。
    • Watcher创建
      • 当模板中使用到数据时,会创建一个Watcher实例。Watcher实例主要负责观察数据的变化,并且在数据变化时更新与之绑定的DOM元素。Watcher会在自身初始化时,读取数据属性的值,从而触发数据劫持的get方法,将自己添加到该属性的依赖列表中。
    • 依赖收集与更新
      • 依赖收集:在get方法中,将当前的Watcher添加到一个全局的依赖收集器(Dep)中。这个Dep类主要用于管理依赖(Watcher),它有一个subs数组,用于存储订阅了该属性变化的Watcher。
      • 更新:当数据发生变化,在set方法中,会遍历Dep中的所有Watcher,调用它们的update方法。Watcher的update方法会执行更新DOM等操作,从而实现数据变化驱动DOM更新的响应式效果。

通过数据劫持和发布 - 订阅模式(观察者模式)的结合,Vue.js能够高效地实现响应式数据绑定,让开发者能够以声明式的方式构建用户界面。

vue3 响应式原理及优化

  1. Vue3响应式原理优化点
    • 性能优化
      • 基于Proxy的响应式系统:Vue3使用Proxy代替Object.defineProperty来实现数据劫持。Proxy可以直接代理整个对象,而不是像Object.defineProperty那样只能劫持对象的已有属性。这意味着可以检测到对象属性的新增和删除操作。例如,在Vue3中,当给一个响应式对象添加新属性时,它会自动成为响应式的,而在Vue2中需要使用Vue.set方法来确保新属性是响应式的。
      • 静态提升(Tree - Shaking):Vue3的编译过程中,编译器会对模板进行静态分析,将一些静态的节点和属性提升出来,这样在组件更新时,这些静态部分就不需要重新渲染,减少了不必要的性能开销。例如,在一个组件的模板中有一些纯文本或者永远不会改变的HTML标签,这些部分可以被静态提升,提高渲染效率。
    • TypeScript支持优化
      • Vue3在设计时就考虑了与TypeScript的良好集成。它的响应式系统提供了更好的类型推断,使得在使用TypeScript编写Vue应用时更加方便和准确。例如,在定义响应式数据时,能够更精确地推断出数据的类型,减少类型错误。
    • Composition API带来的优化
      • 代码组织和复用性:Composition API允许开发者根据逻辑功能来组织代码,而不是像Vue2的Options API那样按照选项(如datamethods等)来划分。这使得代码的复用性更高。例如,在多个组件中都需要使用的数据获取和状态管理逻辑,可以通过自定义的组合式函数进行封装,然后在不同组件中复用。
      • 响应式状态的细粒度控制:在Composition API中,可以更灵活地控制响应式状态的创建和使用。可以在函数内部创建和管理响应式数据,并且可以精确地决定哪些数据需要被响应式处理,哪些不需要,从而提高性能和代码的可维护性。
  2. Vue3响应式原理实现步骤
    • 响应式对象创建(基于Proxy)
      • 步骤一:创建响应式对象:使用reactive函数来创建响应式对象。reactive函数内部会使用Proxy来代理传入的对象。例如:
        import { reactive } from 'vue';
        const state = reactive({count: 0
        });
        
      • 步骤二:Proxy拦截操作Proxy会拦截对象的基本操作,如getsetdeleteProperty等。当访问state.countget操作)时,会进行依赖收集;当修改state.countset操作)时,会触发更新。例如,Proxyget拦截器可能如下:
        const getInterceptor = function(target, key, receiver) {track(target, key); // 进行依赖收集return Reflect.get(target, key, receiver);
        };
        
        这里的track函数用于收集依赖,它会将访问该属性的Watcher(在Vue3中是effect)添加到依赖列表中。
      • 步骤三:依赖收集(track)和触发更新(trigger)
        • 依赖收集(track):在get拦截器中,track函数会根据目标对象和属性,找到对应的Dep(依赖收集器),并将当前的effect(类似于Vue2中的Watcher)添加到Dep中。例如,如果有一个computed属性或者一个渲染函数访问了响应式对象的属性,就会触发track操作。
        • 触发更新(trigger):当响应式对象的属性被修改(在set拦截器中),trigger函数会被调用。trigger会遍历该属性对应的Dep中的所有effect,并执行它们,从而实现更新。例如,修改state.count后,相关的组件渲染函数或者computed属性的计算函数会被重新执行。
    • Computed属性处理
      • 步骤一:创建Computed属性:使用computed函数来创建computed属性。例如:
        import { computed, reactive } from 'vue';
        const state = reactive({count: 0
        });
        const doubleCount = computed(() => state.count * 2);
        
      • 步骤二:计算和缓存机制computed属性会有自己的effect,这个effect会在首次访问时执行计算,并缓存结果。当依赖的响应式属性没有变化时,直接返回缓存结果;当依赖的响应式属性发生变化时,会重新计算。例如,只要state.count没有改变,doubleCount的值就会直接从缓存中获取,而不需要重新计算。
    • WatchEffect和Watch API使用
      • WatchEffectwatchEffect是一个用于自动收集依赖并在依赖变化时重新执行的函数。例如:
        import { watchEffect, reactive } from 'vue';
        const state = reactive({count: 0
        });
        watchEffect(() => {console.log('count has changed to', state.count);
        });
        state.count++;
        
        watchEffect内部的函数访问了state.count,就会自动收集这个依赖。当state.count发生变化时,watchEffect内部的函数会自动重新执行。
      • Watch APIwatch API可以用于更精确地监听特定的数据源(可以是响应式对象的一个属性或者一个getter函数)的变化。例如:
        import { watch, reactive } from 'vue';
        const state = reactive({count: 0
        });
        watch(() => state.count,(newValue, oldValue) => {console.log('count changed from', oldValue, 'to', newValue);}
        );
        state.count++;
        
        这里watch精确地监听了state.count这个属性的变化,并且在变化时执行回调函数,比较新旧值。

fiber

  1. React Fiber架构的背景和目的

    • 背景:随着React应用的复杂性增加,传统的同步渲染方式在处理大型复杂组件树或者高频率更新场景时,会出现性能瓶颈。例如,当有一个包含大量子组件的页面,一次更新可能会导致长时间的阻塞,使得页面响应迟钝。
    • 目的:Fiber架构的主要目的是实现异步可中断的渲染。它将渲染工作拆分成小的单元(Fiber节点),使得React能够在执行渲染任务的过程中,根据任务的优先级暂停、恢复或者重新安排任务,从而提供更流畅的用户体验,尤其在处理复杂的动画、交互以及高优先级更新时非常有用。
  2. Fiber节点的概念和结构

    • 概念:Fiber节点是Fiber架构中的基本单元,它可以看作是对组件、元素或者DOM节点的一种抽象表示。每个Fiber节点包含了组件的状态、更新队列、子节点等信息,并且记录了与渲染任务相关的一些属性,如优先级、是否正在处理等。
    • 结构
      • 属性部分
        • type:表示Fiber节点对应的组件类型,例如是一个函数组件还是类组件。
        • key:用于在列表渲染等场景中区分不同的节点,帮助React确定是否需要更新或重新创建节点。
        • stateNode:对于类组件,这个属性指向组件实例;对于DOM元素,它指向真实的DOM节点。
        • pendingProps和memoizedProps:分别表示即将应用的新属性和上一次渲染时使用的属性,通过比较这两个属性来决定是否需要更新组件。
        • pendingWorkPriority:表示这个Fiber节点任务的优先级,React会根据优先级来安排任务的执行顺序。
      • 关联部分
        • return:指向父级Fiber节点,用于在遍历组件树时返回上一层。
        • child:指向第一个子Fiber节点,用于在遍历组件树时进入下一层。
        • sibling:指向同一层级的下一个Fiber节点,用于在遍历完一个子树后切换到同层的其他子树。
  3. Fiber架构下的更新过程

    • 任务调度(Scheduling)
      • React会根据更新的来源(如用户交互、网络请求返回等)为每个更新任务分配优先级。例如,用户直接操作(如点击按钮)产生的更新通常会被赋予较高的优先级,而一些后台数据更新可能会被赋予较低的优先级。这些更新任务会被放入一个任务队列中,React会根据优先级和当前的资源情况来决定从队列中取出哪些任务进行处理。
    • 渲染阶段(Reconciliation)
      • 阶段一:从根节点开始遍历:React从根Fiber节点开始,按照深度优先遍历的方式遍历组件树。在遍历过程中,它会为每个Fiber节点执行一些操作,如检查属性是否变化、比较新旧状态等,以确定是否需要更新组件。如果需要更新,会创建新的Fiber节点或者更新现有Fiber节点的属性。
      • 阶段二:生成新的Fiber树(Work in Progress Tree):在遍历过程中,React会构建一个新的Fiber树,这个树是在旧的Fiber树基础上更新而来的。这个过程中,React会利用Fiber节点的各种属性来高效地判断哪些组件需要更新、哪些可以复用等。例如,如果一个组件的属性没有变化,React可以直接复用旧的Fiber节点对应的DOM节点,而不需要重新创建。
      • 阶段三:标记副作用(Side Effects):在生成新的Fiber树的过程中,React会标记出一些需要执行副作用的Fiber节点。副作用包括但不限于更新DOM、调用生命周期钩子(在类组件中)、执行useEffect钩子(在函数组件中)等。这些标记会在后续的提交阶段被处理。
    • 提交阶段(Commit)
      • 一旦新的Fiber树构建完成并且副作用被标记好,React就进入提交阶段。在这个阶段,React会根据标记执行相应的副作用。例如,将新的DOM节点插入到文档中、更新现有DOM节点的属性等操作,以将更新后的组件状态反映到实际的页面上。同时,在这个阶段也会执行一些清理工作,如清除旧的Fiber树等。
  4. Fiber架构带来的优势

    • 性能优化
      • 通过异步可中断的渲染,Fiber架构可以避免长时间的渲染阻塞。例如,在一个包含复杂动画的页面中,动画相关的更新可以被赋予较高优先级,React可以暂停其他低优先级的更新任务,优先处理动画更新,从而保证动画的流畅性。
    • 更好的用户体验
      • 由于能够及时响应高优先级的更新,如用户交互,用户会感觉应用更加灵敏。例如,当用户在一个表单中输入内容时,输入相关的更新会被快速处理,而不会因为其他复杂的后台更新而延迟。
    • 支持更复杂的应用场景
      • Fiber架构使得React能够更好地处理大型复杂的组件树。它可以根据任务的优先级和资源情况,灵活地安排渲染任务,从而使得应用在复杂的场景下依然能够保持良好的性能和响应性。

fiber 与 虚拟dom

  1. 虚拟DOM(Virtual DOM)的基本概念和作用

    • 基本概念:虚拟DOM是一种对真实DOM的抽象表示。它是一个JavaScript对象,以树形结构描述了真实DOM的层次结构和节点属性。例如,一个简单的HTML元素 <div id="app"><p>Hello</p></div> 在虚拟DOM中可能被表示为一个对象,如{ type: 'div', props: { id: 'app' }, children: [{ type: 'p', props: {}, children: ['Hello'] }] }
    • 作用
      • 性能优化:在传统的DOM操作中,每次更新都会直接操作真实DOM,而真实DOM的操作是比较昂贵的(因为会引起浏览器的重排和重绘)。虚拟DOM通过在内存中进行比较和计算,找出需要更新的最小部分,然后批量更新真实DOM,减少了不必要的DOM操作次数,从而提高性能。
      • 跨平台兼容:虚拟DOM可以很容易地被转换为其他平台的原生组件表示。例如,React Native使用虚拟DOM的概念来将组件渲染为原生的iOS和Android应用,使得开发者可以使用相似的代码逻辑在不同平台上构建应用。
  2. Fiber架构与虚拟DOM的关系

    • 继承与扩展:Fiber架构是在虚拟DOM基础上的一种改进和扩展。Fiber节点本身可以看作是对虚拟DOM节点的一种增强表示。它继承了虚拟DOM描述组件结构和状态的功能,同时增加了更多与渲染任务管理相关的属性,如任务优先级、是否正在处理等。
    • 更新过程中的协作:在更新过程中,Fiber架构利用虚拟DOM的比较算法来确定组件的更新范围。例如,在Fiber的渲染阶段(Reconciliation),它会比较新旧虚拟DOM树(实际上是新旧Fiber树),通过标记差异来决定哪些组件需要更新、添加或删除。这个过程类似于传统虚拟DOM的Diff算法,但Fiber架构使得这个过程更加灵活和高效,因为它可以根据任务优先级中断和恢复比较过程。
  3. Fiber架构对虚拟DOM更新过程的优化

    • 异步可中断的Diff操作
      • 传统的虚拟DOM Diff操作是同步的,一旦开始就会一直执行直到完成整个组件树的比较。而Fiber架构下,Diff操作可以被中断。例如,当一个高优先级的更新任务(如用户的交互操作)到来时,React可以暂停当前正在进行的低优先级的虚拟DOM Diff操作,先处理高优先级任务。这就好比在一个工厂的生产线上,原本按部就班地组装产品(传统Diff操作),但当有一个紧急订单(高优先级更新)时,可以暂停当前的生产,先处理紧急订单。
    • 更精细的任务划分和优先级调度
      • Fiber将渲染任务划分为一个个小的Fiber节点任务,并为每个任务分配优先级。在虚拟DOM更新过程中,它会根据这些优先级来安排任务的执行顺序。比如,在一个复杂的网页中,页面可视区域内的组件更新可能会被赋予较高优先级,而页面底部或隐藏部分的组件更新优先级较低。这样可以确保最重要的部分先更新,提高用户体验。
    • 更好的内存管理和复用
      • 在构建新的Fiber树(Work in Progress Tree)过程中,Fiber架构会更加精细地考虑组件的复用。它会根据Fiber节点的各种属性(如key属性等)来判断是否可以复用旧的组件和DOM节点。这类似于虚拟DOM的复用策略,但Fiber架构能够在更新过程中更灵活地处理复用情况,减少不必要的内存占用和重新创建DOM节点的操作。
  4. 对比传统虚拟DOM更新方式的优势

    • 响应速度更快
      • 由于Fiber架构能够及时处理高优先级的更新,应用在面对用户交互等紧急情况时能够更快地做出响应。例如,在一个实时聊天应用中,用户发送消息(高优先级更新)能够迅速在界面上显示,而不会因为正在进行的大规模数据更新(低优先级)而延迟。
    • 性能提升在复杂场景下更明显
      • 在处理大型复杂的组件树或者高频率更新场景时,Fiber架构的优势更加突出。传统虚拟DOM更新可能会在这种情况下出现性能瓶颈,而Fiber通过异步可中断的渲染和精细的任务调度,能够更好地平衡性能和用户体验,使应用在复杂场景下依然能够保持流畅。

相关文章:

发布订阅者=>fiber=>虚拟dom

文章目录 vue的响应式原理-发布订阅者模式vue3 响应式原理及优化fiberfiber 与 虚拟dom vue的响应式原理-发布订阅者模式 Vue响应式原理概述 Vue.js的响应式原理是其核心特性之一。它使得当数据发生变化时&#xff0c;与之绑定的DOM元素能够自动更新。其主要基于数据劫持和发布…...

Python-计算机中的码制以及基础运算符(用于分析内存)

记录python学习&#xff0c;直到学会基本的爬虫&#xff0c;使用python搭建接口自动化测试就算学会了&#xff0c;在进阶webui自动化&#xff0c;app自动化 python基础2-码制 计算机中的码制原码&#xff08;True Form&#xff09;反码&#xff08;Ones Complement&#xff09…...

yum 离线软件安装

适用范围 支持YUM软件管理的操作系统&#xff1a; 银河麒麟 服务器操作系统V10统信服务器操作系统V20CentOS 系列 准备 准备一台可以连接互联网并且与离线安装的操作系统相同版本的操作系统&#xff0c;包括指令集类型相同。 安装下载工具 查询是否已经安装下载工具 yum…...

【C语言】17. 数据在内存中的存储

文章目录 一、整数在内存中的存储二、⼤⼩端字节序和字节序判断1、什么是⼤⼩端&#xff1f;2、为什么有⼤⼩端?3、练习1&#xff09;练习12&#xff09;练习23&#xff09;练习34&#xff09;练习45&#xff09; 练习56&#xff09;练习6 三、浮点数在内存中的存储1、浮点数的…...

二叉树概述

目录 一、二叉树的基本结构 二、二叉树的遍历 1.前序 2.中序 3.后序 4.层序遍历 三.计算二叉树的相关参数 1.计算节点总个数 2.计算叶子节点的个数 3.计算树的高度 4.计算第k层的子树个数 5.查找树中val为x的节点 四.刷题 1.单值二叉树 2.检查两棵树是否相同 3.一…...

【开源免费】基于SpringBoot+Vue.JS图书进销存管理系统(JAVA毕业设计)

博主说明&#xff1a;本文项目编号 T 082 &#xff0c;文末自助获取源码 \color{red}{T082&#xff0c;文末自助获取源码} T082&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…...

惠普M126a连接共享打印机故障0x000006ba,系统不支持请求的命令,print spooler重复停止

故障说明&#xff1a;直连惠普M126a打印机正常打印&#xff0c;通过共享连接的报故障。 目前已知有三种故障&#xff1a; 1、0x000006ba报错2、系统不支持请求的命令3、print spooler重复停止&#xff08;或者&#xff0c;print spooler没有停止依然报故障&#xff09; 解决方…...

Chainlit集成LlamaIndex实现一个通过用户聊天对话的酒店预定系统

Agent 简介 “Agent”是一个自动推理和决策引擎。它接受用户输入/查询,并为执行该查询做出内部决策,以便返回正确的结果。关键的代理组件可以包括但不限于: 把复杂的问题分解成小问题选择要使用的外部工具+调用工具的参数计划一系列的任务将以前完成的任务存储在内存模块中…...

计算机网络之网络层超详细讲解

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 计算机网络之网络层超详细讲解 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; …...

代码随想录算法训练营day51|动态规划part13

回文子串 回文子串这里的递推式不太一样&#xff0c;dp[i] 和 dp[i-1] &#xff0c;dp[i 1] 看上去都没啥关系。所以要回归到回文的定义 而我们发现&#xff0c;判断一个子字符串&#xff08;字符串下标范围[i,j]&#xff09;是否回文&#xff0c;依赖于&#xff0c;子字符串…...

ESP8266自制桌宠机器狗

看到别人的桌宠机器狗有没有想要拥有一台的冲动,其实我们可以使用少量的资金自制一台机器狗 1 硬件 esp8266芯片 舵机 超声波传感器 2 接线 ESP8266配件...

【力扣】409.最长回文串

问题描述 思路解析 因为同时包含大小写字母&#xff0c;直接创建个ASCII表大小的桶来标记又因为是要回文子串&#xff0c;所以偶数个数的一定可以那么同时&#xff0c;对于出现奇数次数的&#xff0c;我没需要他们的次数-1&#xff0c;变为偶数&#xff0c;并且可以标记出现过…...

git 拉取代码时报错 gitignore Please move or remove them before you merge.

git 拉取代码时报错&#xff0c; The following untracked working tree files would be overwritten by merge: .gitignore Please move or remove them before you merge. 当你在使用 Git 进行代码拉取&#xff08;通常是执行 git pull 或 git merge 命令&#xff09;时遇到这…...

19,[极客大挑战 2019]PHP1

这个好玩 看到备份网站字眼&#xff0c;用dirsearch扫描 在kali里打开 爆破出一个www.zip文件 访问一下 解压后是这个页面 class.php <?php include flag.php; error_reporting(0); class Name{ private $username nonono; private $password yesyes; publi…...

MQTT消息服务器mosquitto介绍及说明

Mosquitto是一个开源的消息代理软件&#xff0c;支持MQTT协议&#xff08;消息队列遥测传输协议&#xff09;。MQTT是一种轻量级的发布/订阅消息传输协议&#xff0c;专为低带宽、不可靠网络环境下的物联网设备通信而设计。以下是关于Mosquitto服务器的一些介绍和说明&#xff…...

uniapp结合movable-area与movable-view实现拖拽功能

前言 因为公司业务开发需要拖拽功能。 ps&#xff1a;该功能只能针对高度一致的&#xff0c;如果高度不一致需要另外二开 演示 开始 <template><view style"height: 100%;"><movable-area :style"{width: 100%, height: allHeight px}"…...

十九(GIT2)、token、黑马就业数据平台(页面访问控制(token)、首页统计数据、登录状态失效)、axios请求及响应拦截器、Git远程仓库

1. JWT介绍 JSON Web Token 是目前最为流行的跨域认证解决方案&#xff0c;本质就是一个包含信息的字符串。 如何获取&#xff1a;在使用 JWT 身份验证中&#xff0c;当用户使用其凭据成功登录时&#xff0c;将返回 JSON Web Token&#xff08;令牌&#xff09;。 作用&#xf…...

文生图模型开源之光!ComfyUI - AuraFlow本地部署教程

一、模型介绍 AuraFlow 是唯一一个真正开源的文生图模型&#xff0c;由Fal团队开源&#xff0c;其代码和权重都放在了 FOSS 许可证下。基于 6.8B 参数优化模型架构&#xff0c;采用最大更新参数化技术&#xff0c;还重新标注数据集提升指令遵循质量。在物体空间和色彩上有优势…...

spring boot之@Import注解的应用

我们知道spring boot会通过ComponentScan定义包扫描路径进行业务定义的bean的加载&#xff0c;但是对于很多不在此包路径下定义的bean怎么办呢&#xff1f;比如其他jar包中定义的。这时候import就发挥作用了&#xff0c;通过它也可以实现bean的定义。具体是怎么做的呢&#xff…...

【记录】用JUnit 4的@Test注解时报错java.lang.NullPointerException的原因与解决方法

项目场景&#xff1a; 在练习黑马点评的逻辑过期解决缓存击穿时&#xff0c;编写了一个预热缓存数据的单元测试 SpringBootTest public class HmDianPingApplicationTests {Resourceprivate ShopServiceImpl shopService;Testpublic void testSaveShop() throws InterruptedE…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...

ubuntu22.04 安装docker 和docker-compose

首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

VASP软件在第一性原理计算中的应用-测试GO

VASP软件在第一性原理计算中的应用 VASP是由维也纳大学Hafner小组开发的一款功能强大的第一性原理计算软件&#xff0c;广泛应用于材料科学、凝聚态物理、化学和纳米技术等领域。 VASP的核心功能与应用 1. 电子结构计算 VASP最突出的功能是进行高精度的电子结构计算&#xff…...

Heygem50系显卡合成的视频声音杂音模糊解决方案

如果你在使用50系显卡有杂音的情况&#xff0c;可能还是官方适配问题&#xff0c;可以使用以下方案进行解决&#xff1a; 方案一&#xff1a;剪映替换音色&#xff08;简单适合普通玩家&#xff09; 使用剪映换音色即可&#xff0c;口型还是对上的&#xff0c;没有剪映vip的&…...

OCC笔记:TDF_Label中有多个相同类型属性

注&#xff1a;OCCT版本&#xff1a;7.9.1 TDF_Label中有多个相同类型的属性的方案 OCAF imposes the restriction that only one attribute type may be allocated to one label. It is necessary to take into account the design of the application data tree. For exampl…...