淺析 Spring 啟動過程:從源碼到核心方法

淺析 Spring 啟動過程:從源碼到核心方法

  • 一、Spring 注解方式啟動類 Demo
  • 二、Spring 啟動過程源碼解析
    • ?AnnotationConfigApplicationContext構造函數
    • refresh()方法詳解
  • 三、refresh()的核心方法/步驟
    • obtainFreshBeanFactory() - 獲取Bean工廠
    • prepareBeanFactory(beanFactory) - 配置 Bean 工廠
    • invokeBeanFactoryPostProcessors() - 調用注冊的BeanFactoryPostProcessor實現類
    • finishBeanFactoryInitialization() - 實例化、初始化所有剩余的單例 Bean【重要】【重要】【重要】

在這里插入圖片描述
在 Java 企業級開發中,Spring 框架是最常用的基礎框架之一。了解 Spring 的啟動過程,對于理解 Spring 的工作原理、優化應用性能以及排查問題都有著至關重要的作用。本文將結合純 Spring 的注解方式啟動類,深入解讀 Spring 啟動過程的源碼,重點分析 refresh()方法及其包含的關鍵步驟。

一、Spring 注解方式啟動類 Demo

首先,我們創建一個簡單的 Spring 項目,通過注解方式啟動 Spring 容器。

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@ComponentScan("com.coderzpw")      // 掃描該路徑下的包
@Configuration
public class AppConfig {public static void main(String[] args) {// Spring容器啟動AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);// 可以在這里獲取Bean進行后續操作// 容器關閉applicationContext.close();}
}

在上述代碼中:

  • @Configuration注解表明該類是一個配置類,用于替代傳統的 XML 配置文件。
  • @ComponentScan("com.coderzpw") 注解用于掃描指定包及其子包下的所有@Component@Service@Repository@Controller等注解標注的類,并將它們注冊為 Spring 容器中的 Bean。
  • main方法中,通過AnnotationConfigApplicationContext來創建 Spring 應用上下文,傳入配置類AppConfig.class,從而啟動 Spring 容器。

二、Spring 啟動過程源碼解析

當我們調用AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);時,Spring 的啟動過程便開始了。接下來我們深入源碼,一探究竟。

?AnnotationConfigApplicationContext構造函數

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {this();register(annotatedClasses);refresh();
}

上述代碼中:

  • this()調用了無參構造函數,在無參構造函數中會初始化readerscanner,用于讀取配置類和掃描 Bean。
  • register(componentClasses)方法將傳入的配置類注冊到容器中。
  • 最后調用的refresh()方法是 Spring 啟動過程的核心,它完成了 Spring 容器的初始化、Bean 的加載、配置的解析等一系列關鍵操作

refresh()方法詳解

對 BeanPostProcessor、BeanFactoryPostProcessor不熟悉的同學可以查看下面文章:
【Spring BeanFactoryPostProcessor:機制解讀與代碼實踐】
【Spring BeanPostProcessor:機制解讀與代碼實踐】

refresh()方法位于AbstractApplicationContext類中,其源碼如下:

@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 準備上下文環境,記錄啟動時間,標記活動狀態等prepareRefresh();// 告訴子類刷新內部bean工廠ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 準備bean工廠,設置一些屬性,如類加載器、表達式解析器等prepareBeanFactory(beanFactory);try {// 允許子類在bean工廠準備好后進行進一步的設置postProcessBeanFactory(beanFactory);// 執行BeanFactoryPostProcessor接口的實現類,在bean實例化之前修改bean的定義invokeBeanFactoryPostProcessors(beanFactory);// 注冊BeanPostProcessor接口的實現類,用于在bean實例化、配置和初始化前后進行處理registerBeanPostProcessors(beanFactory);// 初始化消息源,用于國際化等功能initMessageSource();// 初始化應用事件廣播器initApplicationEventMulticaster();// 留給子類初始化其他特殊bean的鉤子方法onRefresh();// 注冊監聽器到事件廣播器registerListeners();// 實例化所有剩余的非惰性單例beanfinishBeanFactoryInitialization(beanFactory);// 完成刷新過程,發布容器刷新完成事件等finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}
}

refresh()方法主要包含 12 個步驟,每個步驟都承擔著不同的職責:

  1. prepareRefresh();
    【準備工作】
    作用:在開始刷新容器之前,進行一些準備工作,如設置容器的啟動時間、標記容器為活躍狀態、清除緩存等。這是 IoC 容器啟動的前奏,為后續的初始化操作做好準備。
  2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    【獲取Bean工廠】
    作用獲取或創建一個新的 BeanFactory 實例,BeanFactory 是 Spring IoC 容器的核心,負責管理 Bean 的定義和實例化。這個步驟是 IoC 容器啟動的基礎,后續的 Bean 加載和創建都依賴于BeanFactory。(重要:XML配置形勢下,加載BeanDefinition就是在這個步驟,具體方法步驟:obtainFreshBeanFactory -> refreshBeanFactory -> loadBeanDefinitions
  3. prepareBeanFactory(beanFactory);
    【配置 Bean 工廠】【為BeanFactory做基礎的配置】
    作用:對獲取到的 BeanFactory 進行一些默認配置,如設置類加載器、添加默認的Bean 后置處理器(例如ApplicationContextAwareProcessor、ApplicationListenerDetector)、設置表達式解析器等。這些配置會影響后續 Bean 的創建和初始化過程。
  4. postProcessBeanFactory(beanFactory);
    【后置處理 Bean 工廠】【子類做后置擴展處理】
    作用:允許子類對 BeanFactory 進行額外的后置處理,例如注冊自定義的 BeanPostProcessor 或 BeanFactoryPostProcessor。這為開發者提供了擴展 IoC 容器功能的機會。
  5. invokeBeanFactoryPostProcessors(beanFactory);
    【調用注冊的BeanFactoryPostProcessor實現類】
    作用調用所有注冊的 BeanFactoryPostProcessor 實現類,這些處理器可以在 Bean 定義加載完成后、Bean 實例化之前對 Bean 定義進行修改。通過這個步驟,開發者可以動態地修改 Bean 的定義信息。
  6. registerBeanPostProcessors(beanFactory);
    【注冊 BeanPostProcessor的實現類】【只注冊、不調用】
    作用注冊所有的 BeanPostProcessor實現類,這些處理器會在Bean實例化、配置和初始化前后進行額外的處理。例如,AutowiredAnnotationBeanPostProcessor可以處理@Autowired注解,實現自動裝配功能
  7. initMessageSource();
    【初始化消息源】
    作用初始化消息源,用于支持國際化和消息解析。這在需要處理多語言的應用程序中非常有用。
  8. initApplicationEventMulticaster();
    【初始化應用[事件廣播器]】
    [事件廣播器]:負責將事件廣播給所有注冊的監聽器。
    [事件發布者(ApplicationEventPublisher)]:負責發布事件
    [事件監聽器(ApplicationListener)]:負責監聽特定類型的事件
    作用初始化應用事件廣播器,用于發布和監聽應用程序中的事件。Spring 的事件機制允許組件之間進行松耦合的通信。
  9. onRefresh();
    【留給子類擴展】【空實現】【子類特定的刷新操作】
    作用:允許子類實現特定的刷新邏輯,例如在 WebApplicationContext 中,會創建和初始化 Servlet 上下文。
  10. registerListeners();
    【注冊監聽器】
    作用注冊應用程序中的事件監聽器,這些監聽器會監聽由事件廣播器發布的事件,并執行相應的處理邏輯。
  11. finishBeanFactoryInitialization(beanFactory);
    【實例化所有剩余的單例 Bean】【Bean 實例化、初始化、BeanPostProcessor的執行】
    作用:實例化所有剩余的單例 Bean,這是 IoC 容器啟動的核心步驟之一。在這個過程中,BeanFactory 會根據 Bean 定義創建 Bean 實例,并進行依賴注入和初始化操作。
  12. finishRefresh();
    【完成刷新】
    作用完成容器的刷新工作,清除緩存、發布容器刷新完成事件等。此時,IoC 容器已經完全啟動并可以正常使用。

三、refresh()的核心方法/步驟

obtainFreshBeanFactory() - 獲取Bean工廠

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();    // 觸發BeanDefinition加載return getBeanFactory();
}

obtainFreshBeanFactory()是Spring容器啟動流程中的核心方法,其核心性體現在:

  • BeanFactory生命周期起點:負責創建或刷新BeanFactory實例,是IoC容器誕生的起點
  • 配置加載入口:觸發XML配置的解析流程,將配置轉化為可操作的BeanDefinition對象

BeanDefinition加載流程解析

1. 傳統Spring項目(XML配置為例)

核心步驟

  • refreshBeanFactory():銷毀舊容器 → 創建DefaultListableBeanFactory → 加載BeanDefinition
  • loadBeanDefinitions():通過XmlBeanDefinitionReader解析XML文件,生成BeanDefinition并注冊

源碼示例

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// ....initBeanDefinitionReader(beanDefinitionReader);loadBeanDefinitions(beanDefinitionReader);
}

2. SpringBoot項目(注解驅動)

  • 實現差異:
    • 本質使用GenericApplicationContext代替AbstractRefreshableApplicationContext
    • obtainFreshBeanFactory()僅設置序列化ID,不執行配置加載
  • 實際加載入口:
    • ConfigurationClassPostProcessor(后置處理器)掃描@Configuration
    • @ComponentScan注解觸發包掃描,動態注冊BeanDefinition

prepareBeanFactory(beanFactory) - 配置 Bean 工廠

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 告訴內部 Bean 工廠使用上下文的類加載器等。beanFactory.setBeanClassLoader(getClassLoader());beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// 注冊ApplicationContextAwareProcessor (ApplicationContextAwareProcessor負責處理實現了ApplicationContextAware的類)beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));// // 注冊早期后處理器,用于將內部 bean 檢測為 ApplicationListeners。beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// ...// 注冊默認的 環境Beanif (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}
}

核心配置

  • 設置類加載器
  • 添加默認的Bean 后置處理器(例如ApplicationContextAwareProcessorApplicationListenerDetector
  • 注冊默認的 環境bean

invokeBeanFactoryPostProcessors() - 調用注冊的BeanFactoryPostProcessor實現類

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 【核心】調用 BeanFactoryPostProcessorsPostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)// ...
}

進入invokeBeanFactoryPostProcessors

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {// 【 1. 處理所有 BeanDefinitionRegistryPostProcessor(子接口)】if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =new LinkedList<BeanDefinitionRegistryPostProcessor>();// 分階段處理:PriorityOrdered → Ordered → 普通實現// 執行 PriorityOrdered invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);// 執行 OrderedinvokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);// 執行 普通實現invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {// Invoke factory processors registered with the context instance.invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}// ...// 【 2. 處理所有 BeanFactoryPostProcessor】// 分階段處理:PriorityOrdered → Ordered → 普通實現List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();List<String> orderedPostProcessorNames = new ArrayList<String>();List<String> nonOrderedPostProcessorNames = new ArrayList<String>();for (String ppName : postProcessorNames) {if (processedBeans.contains(ppName)) {// skip - already processed in first phase above}else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}// 執行 PriorityOrdered invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// 執行 OrderedinvokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// 執行 普通實現invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);// ...
}

具體執行方法:invokeBeanFactoryPostProcessors

/*** 調用給定的BeanFactoryPostProcessor bean。*/
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {for (BeanFactoryPostProcessor postProcessor : postProcessors) {// 執行具體的postProcessBeanFactory方法postProcessor.postProcessBeanFactory(beanFactory);}
}

其中ConfigurationClassPostProcessorBeanFactoryPostProcessor的子類,會在該階段執行其后置處理邏輯。負責解析 @Configuration 類及其注解(如 @ComponentScan@Bean),動態注冊新的 BeanDefinition
ConfigurationClassPostProcessor核心功能:

  1. 掃描配置類: 識別 @Configuration 類,解析其上的 @ComponentScan@Import 等注解
  2. 處理條件注解: 根據 @Conditional 注解判斷是否注冊對應的 BeanDefinition

finishBeanFactoryInitialization() - 實例化、初始化所有剩余的單例 Bean【重要】【重要】【重要】

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// ...// 實例化所有剩余的 (非 lazy-init) 單例。【核心】【重要】【bean實例化 -> 屬性填充 -> 初始化】beanFactory.preInstantiateSingletons();
}

finishBeanFactoryInitialization() 方法核心作用總結:

  1. 初始化基礎服務
    • 設置類型轉換服務(ConversionService),處理 @Value 和屬性注入的類型轉換
  2. 凍結 Bean 配置
    • 調用 freezeConfiguration(),停止修改 BeanDefinition,確保后續實例化過程的線程安全
  3. 實例化非懶加載單例 Bean
    • 遍歷所有 BeanDefinition,觸發 getBean() 實例化非抽象、單例且非懶加載的 Bean
    • 特殊處理 FactoryBean:根據 SmartFactoryBean.isEagerInit() 判斷是否立即生成目標對象
  4. 初始化回調與擴展
    • 觸發 SmartInitializingSingleton.afterSingletonsInstantiated(),在所有單例創建完成后執行自定義邏輯
    • 處理 LoadTimeWeaverAware 接口,支持類加載期字節碼增強(如 AspectJ LTW)
  5. 資源回收與優化
    • 釋放臨時類加載器(TempClassLoader),避免內存泄漏

該方法涉及 Spring IoC 最復雜的實例化階段,包括 bean的實例化屬性填充(解決循環依賴)、BeanPostProcesser的前置處理(部分Aware處理邏輯)、bean的初始化BeanPostProcesser的后置處理(AOP 代理的生成時機)等細節

一篇文章是講解不清楚finishBeanFactoryInitialization()的,請期待后續總結 ?ヽ(°▽°)ノ?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/81118.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81118.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/81118.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

貝葉斯優化Transformer融合支持向量機多變量回歸預測,附相關性氣泡圖、散點密度圖,Matlab實現

貝葉斯優化Transformer融合支持向量機多變量回歸預測&#xff0c;附相關性氣泡圖、散點密度圖&#xff0c;Matlab實現 目錄 貝葉斯優化Transformer融合支持向量機多變量回歸預測&#xff0c;附相關性氣泡圖、散點密度圖&#xff0c;Matlab實現效果一覽基本介紹程序設計參考資料…

智慧化系統安全分析報告

智慧化系統的安全背景與現狀 一、政策法規背景 &#xff08;一&#xff09;全球主要國家/地區政策對比 地區政策名稱核心內容實施時間特點中國《生成式人工智能服務管理暫行辦法》明確服務提供者責任&#xff0c;強調數據合法、隱私保護&#xff0c;禁止生成違法內容2023年8…

【學習筆記】點云自動化聚類簡要總結

聚類是將將具有相似特征劃分為相同點集的操作。 基于空間鄰近性的方法 核心思想&#xff1a;依據點的空間距離進行分組 歐式聚類&#xff08;DBSCAN&#xff0c;KD-tree) 原理&#xff1a;基于半徑搜索和最小點數擴展簇。 優點&#xff1a;適應不規則形狀&#xff0c;無需預…

全志F10c200開發筆記——移植uboot

相關資料&#xff1a; &#xff08;二&#xff09;uboot移植--從零開始自制linux掌上電腦&#xff08;F1C200S)&#xff1c;嵌入式項目&#xff1e;-CSDN博客 F1C200S挖坑日記&#xff08;3&#xff09;——Uboot編譯篇_f1c200s uboot-CSDN博客 一、安裝編譯器 Linaro Rele…

常見WEB漏洞----暴力破解

什么是暴力破解 暴力破解 (Brue Force) 是一種攻擊方法 (窮舉法)&#xff0c;簡稱為“爆破”&#xff0c;黑客通過反復猜解和實驗&#xff0c;旨在以暴力手段登入、訪問目標主機獲取服務&#xff0c;破壞系統安全&#xff0c;其屬于 ATT&CK技術中的一種&#xff0c;常利用…

ARM A64 LDR指令

ARM A64 LDR指令 1 LDR (immediate)1.1 Post-index1.2 Pre-index1.3 Unsigned offset 2 LDR (literal)3 LDR (register)4 其他LDR指令變體4.1 LDRB (immediate)4.1.1 Post-index4.1.2 Pre-index4.1.3 Unsigned offset 4.2 LDRB (register)4.3 LDRH (immediate)4.3.1 Post-index…

2.安卓逆向2-adb指令

免責聲明&#xff1a;內容僅供學習參考&#xff0c;請合法利用知識&#xff0c;禁止進行違法犯罪活動&#xff01; 內容參考于&#xff1a;圖靈Python學院 工具下載&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取碼&#xff1…

Obsidian Callouts標注框語法

Obsidian 從 0.14 版本開始原生支持 Callouts&#xff1a; 語法基于 Markdown 引用塊&#xff08;>&#xff09;擴展&#xff1a; 語法格式如下&#xff1a; > [!類型] 可選標題 > 內容支持 **Markdown 格式**、[[內部鏈接]] 和嵌入文件。預覽 可選類型一覽&#xf…

nt!MiAllocateWsle函數分析之設置Wsle[WorkingSetIndex]

第一部分&#xff1a; 1: kd> p nt!MiAddValidPageToWorkingSet0xa9: 80a83c13 e8da9afcff call nt!MiAllocateWsle (80a4d6f2) 1: kd> t nt!MiAllocateWsle: 80a4d6f2 55 push ebp 1: kd> dv WsInfo 0x8953a1f8 PointerPte …

docker 命令操作大全

1 Docker Hello World 簡單命令 docker run ubuntu:15.10 /bin/echo "Hello world" docker run&#xff1a;啟動一個新容器。 ubuntu:15.10&#xff1a;使用的 Docker 鏡像&#xff08;Ubuntu 15.10 版本&#xff09;。 Docker 首先從本地主機上查找鏡像是否存在&a…

【軟件工程】基于機器學習的多缺陷定位

基于機器學習的多缺陷定位&#xff08;Multi-Dault Localization, MDL&#xff09;是軟件工程和自動化測試領域的重要研究方向&#xff0c;旨在通過機器學習技術高效識別代碼中多個潛在缺陷的位置。以下從方法、挑戰、應用場景及未來方向展開分析&#xff1a; 一、核心方法 監督…

用MCP往ppt文件里插入系統架構圖

文章目錄 一、技術架構解析1. Markdown解析模塊(markdown_to_hierarchy)2. 動態布局引擎(give_hierarchy_positions)3. PPTX生成模塊(generate_pptx)二、核心技術亮點1. 自適應布局算法2. MCP服務集成三、工程實踐建議1. 性能優化方向2. 樣式擴展方案3. 部署實踐四、應用…

CS016-2-unity ecs

目錄 【23】射擊改進 【24】僵尸生成器 ?編輯【25】隨機行走 【27】射擊光效 【23】射擊改進 a. 當距離目標太遠的時候&#xff0c;要繼續移動。而當距離目標到達攻擊距離之后&#xff0c;則停止移動。 上圖中的if&#xff1a;判斷自身和目標的距離是否大于攻擊距離&#…

新能源汽車制動系統建模全解析——從理論到工程應用

《純電動輕卡制動系統建模全解析&#xff1a;車速-阻力擬合、剎車力模型與旋轉質量轉換系數優化》 摘要 本文以純電動輕卡為研究對象&#xff0c;系統解析制動系統建模核心參數優化方法&#xff0c;涵蓋&#xff1a; 車速-阻力曲線擬合&#xff08;MATLAB實現與模型驗證&…

函數專題1

函數的定義 函數的基本寫法如下所示&#xff1a; def function_name(parameter1, parameter2, ...):"""Docstring: 描述函數的功能、參數和返回值 (可選但強烈推薦)"""# 函數體: 實現功能的代碼# ...return value # 可選&#xff0c;用于返回結…

紅黑樹:數據世界的平衡守護者

在 C 算法的神秘森林里&#xff0c;紅黑樹是一棵充滿智慧的 “魔法樹”。它既不像普通二叉搜索樹那樣容易失衡&#xff0c;也不像 AVL 樹對平衡要求那么苛刻。作為 C 算法小白&#xff0c;今天就和大家一起深入探索紅黑樹的奧秘&#xff0c;看看它是如何成為數據世界的平衡守護…

【hot100-動態規劃-139.單詞拆分】

力扣139.單詞拆分 本題要求判斷給定的字符串 s 是否可以被空格拆分為一個或多個在字典 wordDict 中出現的單詞,且不要求字典中出現的單詞全部都使用,并且字典中的單詞可以重復使用,這是一個典型的動態規劃問題。 動態規劃思路 定義狀態: 定義一個布爾類型的數組 dp,其中…

ZFile與Cpolar技術結合實現遠程數據實時訪問與集中管理的可行性分析

文章目錄 前言1.關于ZFile2.本地部署ZFile3.ZFile本地訪問測試4.ZFile的配置5.cpolar內網穿透工具安裝6.創建遠程連接公網地址7.固定ZFile公網地址 前言 在信息爆炸的年代&#xff0c;每個現代人都在數字浪潮中扮演著獨特的角色。不論是商務精英、影像創作者還是學術達人&…

Vue2在子組件上使用v-model實現數據的雙向綁定、.sync修飾符

1、v-model 先看示例&#xff1a; //父組件<template><ChildComponent v-model"parentData" /> </template><script> import ChildComponent from ./ChildComponent.vue;export default {components: {ChildComponent},data() {return {pa…

自學嵌入式 day 18 - 數據結構 1

數據結構 相互之間存在一種或多種特定關系的數據元素的集合 1.特定關系&#xff1a; &#xff08;1&#xff09;邏輯結構&#xff1a; ①集合&#xff1a;所有在同一個集合中&#xff0c;關系平等。 ②線性關系&#xff1a;數據和數據之間是一對一的關系。&#xff08;數組…