SpringBoot(源码解析 + 实现底层机制)

文章目录

    • 1.搭建SpringBoot底层机制开发环境
        • 1.创建maven项目
        • 2.使用Git管理项目(可以略过)
          • 1.创建一个github存储库
          • 2.克隆到本地,复制文件夹的内容
          • 3.粘贴到idea项目文件夹,将其作为本地仓库与远程仓库关联
        • 3.pom.xml 引入父工程和场景启动器
        • 4.编写运行类
        • 5.启动运行类,思考:tomcat怎么启动的?
    • 2.@Configuration机制梳理
        • 1.环境搭建
          • 1.文件目录
          • 2.Dog.java
          • 3.Config.java 注入单例Dog对象
          • 4.MainApp.java测试是否能够获取bean
          • 5.成功获取
        • 2.机制分析
          • 1.简述
          • 2.图解
    • 3.SpringBoot是怎么启动Tomcat的?
        • 1.环境搭建
          • 1.文件目录
          • 2.HiController.java
          • 3.测试访问
        • 2.源码分析
          • 1.需求分析
          • 2.创建容器过程
            • 1.run方法打断点
            • 2.进入
            • 3.进入
            • 4.进入 SpringApplication
            • 5.继续进入
            • 6.放行到创建容器的那个方法
            • 7.进入
            • 8.继续进入
            • 9.下一步
            • 10.跳出回到createApplicationContext()方法
          • 3.找到createWebServer()
            • 1.打断点
            • 2.放行,并查看目前的容器
            • 3.进入并执行到refresh方法
            • 4.进入
            • 5.再进入
            • 6.进入
            • 7.放行到那个断点
            • 8.进入
            • 9.下一步,找到了createWebServer方法
          • 4.启动Tomcat
            • 1.进入
            • 2.放行到断点并进入getWebServer
            • 3.进入
            • 4.直接跳出
            • 5.放行到下一个断点,然后进入
            • 6.进入,给initialize方法下断点
            • 7.进入,给tomcat.start()下断点
            • 8.直接放行,tomcat启动成功
            • 9.回到afterRefresh方法(一直跳出),此时应用程序上下文已经刷新成功
            • 10.查看目前的容器,完成初始化
    • 4.SpringBoot(实现底层机制)
        • 1.创建Tomcat并启动
          • 1.排除pom.xml中的 spring-boot-starter-tomcat并引入指定版本的Tomcat
          • 2.编写SunSpringApplication.java
            • 1.文件目录
            • 2.创建Tomcat对象,关联Spring容器并启动
            • 3.编写SunMainApp.java,启动Tomcat
            • 4.结果展示
        • 2.创建Spring容器
          • 1.文件目录
          • 2.Monster.java
          • 3.SunConfig.java
          • 4.SunHiController.java
        • 3.完成关联
          • 1.文件目录
          • 2.编写SunWebApplicationInitializer的onStartup方法
          • 3.修改SunSpringApplication设置Tomcat的上下文路径
          • 4.启动测试
            • 1.报错
            • 2.引入对应版本的jasper包即可
            • 3.重新启动
            • 4.访问测试,成功返回结果

1.搭建SpringBoot底层机制开发环境

1.创建maven项目

image-20240313083809194

2.使用Git管理项目(可以略过)
1.创建一个github存储库

image-20240313084026951

2.克隆到本地,复制文件夹的内容

image-20240313084151328

3.粘贴到idea项目文件夹,将其作为本地仓库与远程仓库关联

image-20240313084316050

3.pom.xml 引入父工程和场景启动器
  • 其实父工程只是指定了引入依赖的默认版本
  • 真正的依赖是场景启动器来引入的
  <!--导入springboot父工程-->
  <parent>
    <artifactId>spring-boot-starter-parent</artifactId>
    <groupId>org.springframework.boot</groupId>
    <version>2.5.3</version>
  </parent>
  <dependencies>
    <!--配置maven项目场景启动器,自动导入和web相关的包-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  </dependencies>
4.编写运行类

image-20240313085051775

package com.sun.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author 孙显圣
 * @version 1.0
 */
@SpringBootApplication
public class MainApp {
    public static void main(String[] args) {
        ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args);

    }
}

5.启动运行类,思考:tomcat怎么启动的?

image-20240313085325966

2.@Configuration机制梳理

1.环境搭建
1.文件目录

image-20240313090416238

2.Dog.java
package com.sun.springboot.bean;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Dog {

}

3.Config.java 注入单例Dog对象
package com.sun.springboot.config;

import com.sun.springboot.bean.Dog;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Configuration //作为一个配置类
public class Config {

    @Bean //将单例bean:Dog注入容器
    public Dog dog() {
        return new Dog();
    }
}

4.MainApp.java测试是否能够获取bean
package com.sun.springboot;

import com.sun.media.sound.SoftTuning;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author 孙显圣
 * @version 1.0
 */
@SpringBootApplication
public class MainApp {
    public static void main(String[] args) {
        ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args);

        Object bean = ioc.getBean("dog");
        System.out.println(bean);
    }
}

5.成功获取

image-20240313090607009

2.机制分析
1.简述

image-20240313092732586

2.图解

image-20240313093222725

3.SpringBoot是怎么启动Tomcat的?

1.环境搭建
1.文件目录

image-20240313103409537

2.HiController.java
package com.sun.springboot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 孙显圣
 * @version 1.0
 */
@RestController //将所有方法的返回结果转换成json字符串并返回
public class HiController {
    @RequestMapping("/hi")
    public String hi() {
        return "hi sun HiController";
    }
}

3.测试访问

image-20240313103459664

2.源码分析
1.需求分析

image-20240313103642722

2.创建容器过程
1.run方法打断点

image-20240313104716460

2.进入

image-20240313104909516

3.进入

image-20240313105131573

4.进入 SpringApplication

image-20240313105300872

5.继续进入

image-20240313105551189

6.放行到创建容器的那个方法

image-20240313105648420

7.进入

image-20240313105806714

8.继续进入

image-20240313110021023

9.下一步

image-20240313110106122

10.跳出回到createApplicationContext()方法

image-20240313110138825

3.找到createWebServer()
1.打断点

image-20240313110406371

2.放行,并查看目前的容器

image-20240313110632719

3.进入并执行到refresh方法

image-20240313112421819

4.进入

image-20240313112505918

5.再进入

image-20240313112617071

6.进入

image-20240313112737166

7.放行到那个断点

image-20240313112833276

8.进入

image-20240313112906604

9.下一步,找到了createWebServer方法

image-20240313112932587

4.启动Tomcat
1.进入

image-20240313114552291

2.放行到断点并进入getWebServer

image-20240313114639221

3.进入

image-20240313114709010

4.直接跳出

image-20240313114812126

5.放行到下一个断点,然后进入

image-20240313115149244

6.进入,给initialize方法下断点

image-20240313115415751

7.进入,给tomcat.start()下断点

image-20240313115518081

8.直接放行,tomcat启动成功

image-20240313115552819

9.回到afterRefresh方法(一直跳出),此时应用程序上下文已经刷新成功

image-20240313115657471

10.查看目前的容器,完成初始化

image-20240313115904414

4.SpringBoot(实现底层机制)

1.创建Tomcat并启动
1.排除pom.xml中的 spring-boot-starter-tomcat并引入指定版本的Tomcat
    <!--导入springboot父工程-->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.5.3</version>
    </parent>
    <dependencies>
        <!--配置maven项目场景启动器,自动导入和web相关的包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--  因为要手动创建Tomcat并启动所以,排除spring-boot-starter-tomcat-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--
            引入指定版本的tomcat
            当需要引入自定义版本的tomcat时,需要排除spring-boot-starter-tomcat,否则会出现GenericServlet Not Found的提示
        -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>8.5.75</version>
        </dependency>
    </dependencies>
2.编写SunSpringApplication.java
1.文件目录

image-20240313135110606

2.创建Tomcat对象,关联Spring容器并启动
package com.sun.sunspringboot;


import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import org.springframework.boot.autoconfigure.web.ServerProperties;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class SunSpringApplication {
    /**
     * 创建Tomcat对象,关联Spring容器并启动
     */
    public static void run() {
        try {
            Tomcat tomcat = new Tomcat();
            tomcat.setPort(9090);
            tomcat.start();
            System.out.println("Tomcat在9090端口监听");
            tomcat.getServer().await(); //等待
        } catch (LifecycleException e) {
            throw new RuntimeException(e);
        }
    }
}

3.编写SunMainApp.java,启动Tomcat
package com.sun.sunspringboot;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class SunMainApp {
    public static void main(String[] args) {
        SunSpringApplication.run();
    }
}

4.结果展示

image-20240313135738758

image-20240313135753440

2.创建Spring容器
1.文件目录

image-20240313141342870

2.Monster.java
package com.sun.sunspringboot.bean;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Monster {

}

3.SunConfig.java
package com.sun.sunspringboot.config;

import com.sun.sunspringboot.bean.Monster;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Configuration //配置类
@ComponentScan("com.sun.sunspringboot") //指定要扫描的包
public class SunConfig {
    @Bean
    public Monster monster() {
        return new Monster(); //单例bean注入容器
    }
}

4.SunHiController.java
package com.sun.sunspringboot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 孙显圣
 * @version 1.0
 */
@RestController
public class SunHiController {
    @RequestMapping("/sunhi")
    public String hi() {
        return "hi, SunHiController";
    }
}

3.完成关联
1.文件目录

image-20240313145136167

2.编写SunWebApplicationInitializer的onStartup方法
  • 在Tomcat启动的时候会调用onStartup方法
  • 首先注册配置类,然后将中央控制器放到 servletContext
package com.sun.sunspringboot;

import com.sun.sunspringboot.config.SunConfig;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

/**
 * 1.创建自己的Spring容器
 * 2.关联spring容器的配置
 * 3.完成spring容器配置的bean的创建,依赖注入
 * 4.完成中央控制器,并让其持有Spring容器
 * 5.这里的onStartup是Tomcat调用,并把ServletContext对象传入
 */
public class SunWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        System.out.println("start up");
        AnnotationConfigWebApplicationContext ac =
                new AnnotationConfigWebApplicationContext();

        //完成bean的创建和配置
        ac.register(SunConfig.class); //在ac中注册配置类
        ac.refresh();

        //创建中央控制器
        DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);
        //将中央控制器放到servletContext
        ServletRegistration.Dynamic registration = servletContext.addServlet("app", dispatcherServlet);
        //当tomcat启动时,加载中央控制器
        registration.setLoadOnStartup(1);
        //拦截请求,进行分发处理
        registration.addMapping("/");

    }
}

3.修改SunSpringApplication设置Tomcat的上下文路径

image-20240313145402807

4.启动测试
1.报错

image-20240313145445745

2.引入对应版本的jasper包即可
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>8.5.75</version>
        </dependency>
3.重新启动

image-20240313145910622

4.访问测试,成功返回结果

image-20240313150359027

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【算法积累】辗转相除法

【算法积累】辗转相除法&#xff0c;python实现两种 辗转相除法&#xff08;又称欧几里得算法&#xff09;减法&#xff08;不常用&#xff09;代码实现执行结果 辗转相除法代码实现执行结果 辗转相除法&#xff08;又称欧几里得算法&#xff09; 又称欧几里得算法&#xff0c…

使用Python将多个pdf指定页整合到一个pdf文件中

在工作的一些场景中&#xff0c;有时需要我们将多个pdf文件中的内容提取出来&#xff0c;比如有10个pdf文件&#xff0c;我们要统一打印pdf文件的第一页或者最后一页… 需求分析 我们需要批量提取PDF文件中的任意一页&#xff0c;可以是第一页也可以是中间某一页&#xff0c;…

【C++算法模板】图的存储-邻接矩阵

文章目录 邻接矩阵洛谷3643 图的存储 邻接矩阵 邻接矩阵相比于上一篇博客邻接表的讲解要简单得多 数据结构&#xff0c;如果将二维数组 g g g 定义为全局变量&#xff0c;那默认初始化应该为 0 0 0 &#xff0c;如果题目中存在自环&#xff0c;可以做特判&#xff0c; m e …

微信小程序云开发教程——墨刀原型工具入门(常用组件)

引言 作为一个小白&#xff0c;小北要怎么在短时间内快速学会微信小程序原型设计&#xff1f; “时间紧&#xff0c;任务重”&#xff0c;这意味着学习时必须把握微信小程序原型设计中的重点、难点&#xff0c;而非面面俱到。 要在短时间内理解、掌握一个工具的使用&#xf…

docker+elasticsearch

一&#xff0c;环境准备&#xff1a;安装docker&#xff08;往期文章&#xff09; 二&#xff0c;elasticsearch简介&#xff1a; 用于储存数据 三&#xff0c;部署&#xff1a; 1&#xff09;&#xff0c;拉取镜像 使用本作者提供的java17镜像 2&#xff09;&#xff0c;…

基于大模型的Agent进行测试评估的3种方案

本文首发于博客 基于大模型的Agent进行测试评估的3种方案 我们都知道当前基于大模型构建的 Agent 能力极不稳定&#xff0c;而今年我司产品又在规划接入 Agent 能力&#xff0c;所以在引入之前&#xff0c;需要先设计一套测试框架&#xff0c;来看看各种场景下容错率是否能达…

Linux 基本命令

文章目录 1.echo2.cd3.find4.mkdir5.cp6.rm7.wc8.tar9.tail10.vim11.grep12.sed13 touch14 ls15 快捷键16 ln17 mv18 useradd19 usermod20 su 每天一个Linux命令 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 1.echo 中文 (Chinese): “回声” 或 “输…

分布式链路追踪(一)SkyWalking(2)使用

一、使用方法 1、简介 agent探针可以让我们不修改代码的情况下&#xff0c;对Java应用上使用到的组件进行动态监控&#xff0c;获取运行数据发送到OAP上进行统计和存储。agent探针在Java使用中是使用Java agent技术实现。不需要更改任何代码&#xff0c;Java agent会通过虚拟…

Linux虚拟机安装Qt步骤记录

(一&#xff09;安装命令&#xff0c;按照网上的教程&#xff0c;亲测可行 在终端中依次输入以下命令&#xff0c; 1.更新软件源列表&#xff1a; sudo apt-get update 2.安装Qt开发工具包,windows上我用的是Qt6,根据网上也是初次在Linux上安装Qt,安装版本5应该问题不大&…

智慧农业新篇章:DSSAT模型、APSIM模型、WOFOST与PCSE模型综合应用,引领作物生长模拟与产量预测新潮流

目录 ★WOFOST模型与PCSE模型应用 ★基于R语言APSIM模型进阶应用与参数优化、批量模拟 ★最新DSSAT作物模型建模方法及应用 ★基于Python语言快速批量运行DSSAT模型及交叉融合、扩展应用 ★R语言与作物模型&#xff08;以DSSAT模型为例&#xff09;融合应用 ★遥感数据与…

论文阅读——VSA

VSA: Learning Varied-Size Window Attention in Vision Transformers 方法&#xff1a; 给定输入特征X&#xff0c;VSA首先按照基线方法的例程&#xff0c;将这些标记划分为几个窗口Xw&#xff0c;窗口大小为预定义的w。我们将这些窗口称为默认窗口&#xff0c;并从默认窗口中…

KMP算法——解决字符串匹配问题

一般来说在你没学过KMP算法前&#xff0c;你解决字符串匹配问题会采用BF算法——BF算法&#xff0c;即暴力(Brute Force)算法&#xff0c;是普通的模式匹配算法&#xff0c;BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配&#xff0c;若相等&#xff0c;…

BM1684X搭建sophon c++环境

1:首先安装编译好sophon-sail 比特大陆BM1684X开发环境搭建--SOC mode-CSDN博客 2:在将之前配置的soc-sdk拷贝一份到sdk根目录&#xff0c;将交叉编译好的sail中的build_soc拷贝至soc-sdk文件夹内&#xff1b; cp -rf build_soc/sophon-sail/inlcude soc-sdk cp -rf build_soc…

YOLOv8独家改进:backbone改进 | TransXNet:聚合全局和局部信息的全新CNN-Transformer视觉主干| CVPR2024

💡💡💡本文独家改进:CVPR2024 TransXNet助力检测,代替YOLOv8 Backbone 改进结构图如下: 收录 YOLOv8原创自研 https://blog.csdn.net/m0_63774211/category_12511737.html?spm=1001.2014.3001.5482 💡💡💡全网独家首发创新(原创),适合paper !!! 💡…

突发:日本火箭发射后爆炸

综合路透社、法新社13日消息&#xff0c;现场直播画面显示&#xff0c;日本初创公司Space One火箭发射失败&#xff0c;在半空中发生爆炸。 ▲日媒视频报道截图 据共同社此前介绍&#xff0c;Space One公司11日宣布&#xff0c;13日上午11点零1分将从日本首个民用火箭发射场“…

数据集成平台选型建议

一 数据集成介绍 数据集成平台是一种用于管理和协调数据流动的软件工具或服务。它的主要目标是将来自多个不同数据源的数据整合到一个统一的、易于访问和分析的数据存储库中。这些数据源可以包括数据库、云应用、传感器、日志文件、社交媒体等等。数据集成平台的关键任务是确保…

代码随想录算法训练营第五九天 | 下一个更大元素II、接雨水

目录 下一个更大元素II接雨水 LeetCode 503.下一个更大元素II LeetCode 42. 接雨水 下一个更大元素II 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一…

《Ubuntu20.04环境下的ROS进阶学习2》

一、使用rviz和gazebo实时仿真 本节我们将使用三维可视化工具rviz&#xff08;The Robot Visualization Tool&#xff09;来实时观测gazebo仿真中的激光雷达数据。 二、打开仿真gazebo项目 如果您已经按照 《Ubuntu20.04环境下的ROS进阶学习0》-CSDN博客 如果您已经按照上次的文…

C++作业day2

封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show() #include <iostre…

计算机网络面经八股-HTTP常见的状态码有哪些?

常见状态码&#xff1a; 200&#xff1a;服务器已成功处理了请求。 通常&#xff0c;这表示服务器提供了请求的网页。301 &#xff1a; (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时&#xff0c;会自动将请求者转到新位置。302&…