SpringBoot詳細講解如何創建及刷新Spring容器bean

  • 參考視頻:https://www.bilibili.com/video/BV1Bq4y1Q7GZ?p=6
  • 通過視頻的學習和自身的理解整理出的筆記。

一、前期準備

1.1 創建工程

創建springboot項目,springboot版本為2.5.0,引入spring-boot-starter-web依賴,pom文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

1.2 創建Controller

創建一個簡單的Controller用於測試

@RestController
public class HelloController {
    public void helloController() {
        System.out.println("創建瞭");
    }
    @RequestMapping("hello")
    public String hello() {
        return "hello";
    }
}

二、探究過程

2.1 啟動類

項目的運行隻需要啟動類中一行簡單的代碼,spring容器的創建就是通過SpringApplication.run(SpringbootApplication.class, args)這一行代碼實現的。

其實就是調用瞭靜態的run方法,傳入瞭啟動類的字節碼對象。

2.2 SpringApplication

🔶 run()方法

又調用瞭另一個run方法。

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return run(new Class[]{primarySource}, args);
}

🔶 run()方法

方法的返回值類型為ConfigurableApplicationContextApplicationContext就是Spring的容器。

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
	return new SpringApplication(primarySources).run(args);
}

我們來看看ConfigurableApplicationContext 繼承結構

ConfigurableApplicationContext接口繼承瞭ApplicationContext接口

下面我們通過debug進入run()方法中看看

🔶 run()方法

🔶 createApplicationContext()方法

容器工廠傳入webApplication的類型,這個類型為Servlet應用。

Springboot可以做響應式的Web開發,這時webApplication的類型的類型就不是Servlet。

2.3 ApplicationContextFactory

這裡是一個lambda表達式的寫法,根據webApplicationType的類型返回對應的容器對象。

通過繼承關系圖可以看出,它的確是ApplicationContext

2.4 SpringApplication

🔶 run()方法,容器刷新前

看完瞭createApplicationContext()的過程,我們再次回到run()方法中,此時context已經創建完成。

我們觀察一下context中都有些什麼:

其中包含瞭bean工廠,bean工廠裡有beanDefinitionNames和beanDefinitionMap。(與之前看的spring源碼一樣)

不過這裡都是spring容器內置的beanDefinition對象,沒有我們自定義的helloController,說明現在的容器還沒有刷新。

我們現在獲取不到HelloController的bean對象,當我們能獲取到這個對象時,就說明容器刷新瞭。

🔶 run()方法,容器刷新後

繼續往下運行,我們發現這行代碼執行瞭好久,根據方法名稱也可以看出它的功能就是刷新容器。

刷新後我們成功的獲取到瞭bean對象。

此時beanDefinitionMap中包含瞭138個對象,刷新之前隻包含5個。我們可以在裡面找到helloController(Hello的H變成瞭小寫)

🔶 refreshContext()方法

下面我們看看refreshContext()方法,其中調用瞭refresh()方法。

🔶 refresh()方法

refreshContext()方法中refresh(context)傳入瞭容器對象,在這裡調用瞭這個容器對象的refresh()方法。

後面暫時不往下看瞭。

2.5 結論

在啟動類中調用SpringApplication的run方法時會根據容器的類型創建不同的容器對象,並調用容器的refresh方法。

到此這篇關於SpringBoot詳細講解如何創建及刷新Spring容器bean的文章就介紹到這瞭,更多相關SpringBoot Spring容器bean內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: