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

news2024/11/22 9:10:53

文章目录

    • 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

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

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

相关文章

RUST 每日一省:rust logo收集

rust的logo集合&#xff0c;看看有没有你喜欢的&#xff0c;挑一个吧&#xff1b; GitHub - XuHugo/rust-logo: Collection of logo images for all rust languages 下边只是挑选了几个&#xff0c;更多的还是看github吧。

<2024最新>ChatGPT逆向教程

前言 在使用本篇文章用到的项目以及工具时,需要对其有一定的了解,无法访问以及无法使用的问题作者不承担任何责任,可以自行想办法解决遇到的问题​。 文章若有不合适,有问题的地方,请私聊指出,谢谢~ 准备工具 一台至少 2 核 2G 内存的服务器,推荐是位于香港、新加坡或…

c语言之汉诺塔的实现

思路 汉诺塔问题就是有三个盘子&#xff0c;让我们把其中一个盘子上的东西全移到另一个盘子上&#xff0c;注意的是中途必须满足大东西必须在小东西下面。 这里&#xff0c;我们有A B C三个盘子&#xff0c;假如A上有一个珠子&#xff0c;那我们直接把这一个移到C上就可以&am…

JVM是如何运行的

JVM&#xff08;Java Virtual Machine&#xff0c;Java虚拟机&#xff09;是 Java 程序的运行环境&#xff0c;它负责将 Java 字节码翻译成机器代码并执行。也就是说 Java 代码之所以能够运行&#xff0c;主要是依靠 JVM 来实现的。 JVM 整体的大概执行流程是这样的&#xff1…

数据结构:详解【顺序表】的实现

1. 顺序表的定义 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存储。动态顺序表与数组的本质区别是——根据需要动态的开辟空间大小。 2. 顺序表的功能 动态顺序表的功能一般有如下几个&#xff1a; 初始化顺序表打印顺序…

【网络安全】【密码学】【北京航空航天大学】实验七、流密码【Python实现】

实验七、流密码 实验目的 1、 了解常用的流密码算法&#xff0c;并对其进行实现&#xff1b; 2、 了解常用的伪随机数生成算法&#xff0c;并对其进行实现&#xff1b; 原理简介 流密码&#xff08;Stream Cipher&#xff09;也称为序列密码&#xff0c;它是对称密码算法的…

亚马逊扣店租/注册店铺可以使用虚拟卡吗?

亚马逊扣店租/注册店铺可以使用虚拟卡吗&#xff1f; 可以 一、亚马逊店铺类型 亚马逊提供了不同类型的店铺&#xff0c;以满足不同卖家的需求。以下是最常见的两种店铺类型&#xff1a; 1、亚马逊个人卖家店铺&#xff1a; 这是适合个人卖家的选项&#xff0c;通常称为&qu…

【相关问题解答2】bert中文文本摘要代码:结果输出为一些重复的标点符号和数字

【相关问题解答2】bert中文文本摘要代码 写在最前面问题1&#xff1a;tokenizer.py中encode函数&#xff0c;不能使用lower操作关于提问问题描述1一些建议1问题更新2&#xff1a;结果输出为一些重复的标点符号和数字一些建议21. 数据检查和预处理2. 模型和训练配置3. 过拟合和欠…

Anzo Capital昂首资本基础知识分享:货币对有几组

基础知识大分享&#xff0c;今天Anzo Capital昂首资本分享&#xff1a;外汇市场中的货币对有几组&#xff0c;都是哪些货币对&#xff1f;首先&#xff0c;货币对分为三组: 第一组&#xff1a;主要货币对 包括七种金融工具&#xff0c;占外汇市场所有交易业务的70%以上。 美…

大数据疑难问题2024

问题一&#xff1a; 集群部署一主一备&#xff0c;初始化操作没有问题&#xff0c;有两个namenode,再次重启显示只有node01有namenode 原因&#xff1a;Journalde服务需要在启动启动hdfs和yarn前再次启动 再次启动步骤&#xff1a; 1.启动3台节点的zookeeper&#xff0c;在3…

Thymeleaf 基本使用

01、Thymeleaf 官网地址&#xff1a;Thymeleafhttps://www.thymeleaf.org/ 简介 Thymeleaf是一种服务器端Java模板引擎&#xff0c;用于将数据渲染为HTML、XML、JavaScript等格式&#xff0c;并在Web浏览器中呈现给用户。 具体来说&#xff0c;Thymeleaf充当着视图层的角色&…

代码随想录day19(1)二叉树:对称二叉树(leetcode101)

题目要求&#xff1a;判断一棵二叉树是否轴对称 思路&#xff1a;如果二叉树是对称二叉树&#xff0c;说明此二叉树是可以左右翻转的&#xff0c;所以判断的时候我们同时遍历两棵子树&#xff0c;比较两棵子树的内、外侧是否相等&#xff0c;比较的时候我们实际上比较的是左孩…

Leedcode刷题——5 DFS+回溯

注&#xff1a;以下代码均为c 1. 电话号码的字母组合 思路&#xff1a; 例如&#xff1a;”23“ //1. 我自己写的 vector<string> letterCombinations(string digits) {if(digits "")return {};vector<string> state {""};string s;vecto…

读取txt文件并统计每行最长的单词以及长度

读取txt文件并统计每行最长的单词以及长度 题目 在 D:\\documant.txt 文本中,文件中有若干行英文文本,每行英文文本中有若干个单词&#xff0c;每个单词不会跨行出现每行至多包含100个字符,要求编写一个程序,处理文件,分析各行中的单词,找到每行中的最长单词&#xff0c;分别…

cmd 输入pip 提示不是内部或外部命令,也不是可运行的程序 或批处理文件。

解决办法&#xff1a; 把pthon的安装路径加入到环境变量中&#xff0c;重新打开cmd运行即可 比如&#xff1a;C:\Users\huanhuan\AppData\Local\Programs\Python\Python311\Scripts

测试环境搭建整套大数据系统(十:测试环境minio单节点部署)

一&#xff1a;部署minio 创建安装目录。 mkdir -p /data/server/minio/{bin,data,config,log}bin&#xff1a;二进制文件目录data&#xff1a;数据存储目录config&#xff1a;配置文件目录log&#xff1a;日志文件路径下载二进制安装包到bin目录&#xff0c;或者提前下载好拷…

edm邮件是什么意思:与普通邮件有何不同?

edm邮件是什么意思&#xff1f;如何优化邮件内容以提高转化率&#xff1f; edm邮件因其独特的营销价值而备受关注。那么&#xff0c;edm邮件究竟是什么意思呢&#xff1f;它与普通邮件又有哪些不同呢&#xff1f;下面&#xff0c;AokSend就来为大家介绍一下。 edm邮件的概念与…

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

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

这三个长辈必备的手机模式,你给他们设置了吗?

您是否曾听家里长辈说过手机图标字体太小看起来很吃力&#xff1f;是否曾担心家里长辈在手机上误安装恶意软件&#xff1f;是否曾因为各种骚扰和推销电话而感到困扰&#xff1f;现在&#xff0c;这些问题不再是难题&#xff0c;因为有了华为手机的长辈关怀功能——一键开启放大…

运维打工人,兼职跑外卖的第二个周末

北京&#xff0c;晴&#xff0c;西南风1级。 前序 今天天气还行&#xff0c;赶紧起来&#xff0c;把衣服都洗洗&#xff0c;准备准备&#xff0c;去田老师吃饭早饭了。 一个甜饼、一个茶叶蛋、3元自助粥花费7.5。5个5挺吉利的。 跑外卖的意义 两个字减肥&#xff0c;记录刚入…