SpringBoot学习笔记(4)-分析 SpringBoot 底层机制

文章目录

  • 4. 分析 SpringBoot 底层机制
    • 4.1 Tomcat启动分析
    • 4.2 创建Spring 容器
    • 4.3 将Tomcat 和 Spring 容器关联,并启动 Spring 容器
    • 4.4 扩展-debug查看 ac.refresh()

4. 分析 SpringBoot 底层机制

【Tomcat 启动分析 + Spring 容器初始化+Tomcat 如何关联 Spring 容器 】

4.1 Tomcat启动分析

第一步、修改pom.xml文件,指定我们自己的tomcat

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xjz</groupId>
    <artifactId>xjz-springboot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>

    <!-- 导入 web 项目场景启动器,会自动导入和 web 开发相关依赖,非常方便 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            
            <!-- 在 spring-boot-starter-web 排除内嵌的starter-tomcat -->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
            
        </dependency>

        <!--用我们指定 tomcat 版本来完, 可以到 mvn 去获取依赖坐标. 老韩解读:
            1. 使用指定的 tomcat 才会验证效果 高版本的 tomcat 默认不会真正监听
            2. 使用了指定 tomcat , 需要在 spring-boot-starter-web 排除内嵌的starter-tomcat
            3. 否则会出现包冲突, 提示 GenericServlet Not Found 类似错误
        -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>8.5.75</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jasper -->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>8.5.75</version>
        </dependency>
    </dependencies>


</project>

第二步、创建一个新包,在包下创建我们自己定义的SpringApplication

public class XjzSpringApplication {

    public static void run(){

        try {
            Tomcat tomcat = new Tomcat();
            tomcat.setPort(9090);
            //启动Tomcat
            tomcat.start();
            //等待请求接入
            System.out.println("=====9090=====等待请求");
            tomcat.getServer().await();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

第三步、创建一个启动类

public class XjzMainApp {

    public static void main(String[] args) {
        //调用XjzSpringApplication的run()方法
        XjzSpringApplication.run();
    }
}

第四步、测试看一下控制台结果

image-20230323230859739

image-20230323231118070

查看浏览器请求,http://localhost:9090/,这是没有返回信息

image-20230323231228919

4.2 创建Spring 容器

第一步、创建一个测试Bean

package com.xjz.xjzspringboot.bean;

public class Monster {
}

第二步、创建一个Controller

package com.xjz.xjzspringboot.controller;

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

@RestController
public class XjzHiController {

    @RequestMapping("/xjzhi")
    public String hi(){
        System.out.println("hi,XjzController");
        return "hi,XjzController";
    }
}

第三步、创建Spring的配置文件

package com.xjz.xjzspringboot.config;

import com.xjz.xjzspringboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.xjz.xjzspringboot")
public class XjzConfig {

    /**
     * 1. 通过@Bean 的方式, 将 new 出来的 Bean 对象, 放入到 Spring 容器
     * 2. 该 bean 在 Spring 容器的 name 就是 方法名
     * 3. 通过方法名, 可以得到 new Monster() * @return
     */
    @Bean
    public Monster monster(){
        System.out.println("monster...");
        return new Monster();
    }
}

第四步、创建XjzWebApplicationInitializer.java , 作为 Spring 的容器

package com.xjz.xjzspringboot;

import com.xjz.xjzspringboot.config.XjzConfig;
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;

public class XjzWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        System.out.println("startup....");
        //加载 spring web application configuration
        AnnotationConfigWebApplicationContext ac =
                new AnnotationConfigWebApplicationContext();
        ac.register(XjzConfig.class);
        ac.refresh();//完成bean的创建、和配置

        //创建注册非常重要的分发器 DispatcherServlet
        //注意, 把 spring 容器给到 DispatcherServlet
        //这样就可以做映射分发, 回忆一下我们实现 SpringMVC
        DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration =
                servletContext.addServlet("app", dispatcherServlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/");

    }
}

4.3 将Tomcat 和 Spring 容器关联,并启动 Spring 容器

第一步、修改我们的XjzSpringApplication.java

package com.xjz.xjzspringboot;

import org.apache.catalina.startup.Tomcat;

public class XjzSpringApplication {

    public static void run(){

        try {
            Tomcat tomcat = new Tomcat();
            tomcat.setPort(9090);
            //让 tomcat 可以将请求转发到 spring web 容器, 因此需要关联一把
            //1. /hspboot 就是 tomcat 的 applicaton context
            //理解为工程路径, D:\\hsp.... 就是这个工程的路径
            tomcat.addWebapp("/xjzboot","D:\\IDEA\\hspedu_springboot\\xjz-springboot");
            //启动Tomcat
            tomcat.start();
            //等待请求接入
            System.out.println("=====9090=====等待请求");
            tomcat.getServer().await();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

第二步、运行XjzMainApp测试项目

package com.xjz.xjzspringboot;

public class XjzMainApp {

    public static void main(String[] args) {
        XjzSpringApplication.run();
    }
}

第三步、运行结果

image-20230323232122978

浏览器访问

image-20230323232143240

4.4 扩展-debug查看 ac.refresh()

我们来debug 一下, 看看是否进行 Spring 容器的初始化工作, 可以看到 ac.refresh() 会将HspConfig.class 中配置 Bean 实例化装入到容器中

image-20230323232353857

image-20230323232509625

image-20230323232549496

image-20230323232611346

image-20230323232627489

image-20230323232641075

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

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

相关文章

微软分享修复WinRE BitLocker绕过漏洞的脚本

微软发布了一个脚本&#xff0c;可以更轻松地修补 Windows 恢复环境 (WinRE) 中的 BitLocker 绕过安全漏洞。 此 PowerShell 脚本 (KB5025175) 简化了保护 WinRE 映像以防止试图利用CVE-2022-41099漏洞的过程&#xff0c;该漏洞使攻击者能够绕过 BitLocker 设备加密功能系统存…

jvm03垃圾回收篇

p134 垃圾回收相关章节的说明 p135 什么是GC 为什么需要GC P136 了解早起垃圾回收行为 p137 java自动内存管理介绍 p138垃圾回收相关算法概述 p139引用计数算法的原理及优缺点 p140 python引用计数实施方案 p141 可达性分析算法与GC ROOTS p142 对象的finalization机制 p143 代…

【MyBatis】字段名和属性名不同时,如何处理

目录 前言 1、返回类型&#xff1a;resultType 2、返回字典映射&#xff1a;resultMap 2.1、字段名和属性名不同怎么处理 解决方案一&#xff1a;使用resultMap 解决方案二&#xff1a;使用as起别名 3、多表查询 总结&#xff1a; 前言 在之前的文章中&#xff0c;我们可…

TXT 和 SEV技术小知识

1.Intel TXT 可信执行技术(Trusted Execute Technology&#xff0c;TXT)是Intel公司的可信计算技术&#xff0c;主要通过改造芯片组和CPU&#xff0c;增加安全特性&#xff0c;通过结合一个基于硬件的安全设备—可信平台模块(Trusted Platform Module&#xff0c;TPM)&#xf…

蓝桥杯C/C++VIP试题每日一练之Sine之舞

💛作者主页:静Yu 🧡简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者 💛社区地址:前端知识交流社区 🧡博主的个人博客:静Yu的个人博客 🧡博主的个人笔记本:前端面试题 个人笔记本只记录前端领域的面试题目,项目总结,面试技…

Python 之列表推导式

文章目录参考描述列表推导式举个栗子基本形式一般式基本形式&#xff08;高阶&#xff09;判断使用逻辑运算符笛卡尔积拆解变量污染列表推导式参考 项目描述流畅的 PythonLuciano Ramalho 著 / 安道 吴珂 译搜索引擎Bing 描述 项目描述Python3.10.6 列表推导式 列表推导式是…

python---函数的进阶

函数的进阶 1.8函数的进阶 1.8.1函数作为参数进行传入 1.简介&#xff1a;函数作为范围进行传递到函数中进行操作 2.函数作为参数传入到函数中 3.函数调用和逻辑传入之间的区别 一个是作为数据进行传入&#xff0c;但是调用的函数时一定的一个作为逻辑进行调用&#xff0c;但是…

PTA——1036 跟奥巴马一起编程、1037 在霍格沃茨找零钱、1038 统计同成绩学生、1039 到底买不买、1040 有几个PAT

1036 跟奥巴马一起编程 解决代码 模拟题目即可。 #include<iostream> #include<vector> #include<algorithm> using namespace std; int main(){int n;char c;cin>>n>>c;double col(double)n/2;int n0n/2;if(col>n00.4) n01; for(int i0;i&…

华为路由器 基本ACL配置

1、什么是ACL&#xff1f; 访问控制列表ACL&#xff08;Access Control List&#xff09;是由一条或多条规则组成的集合。所谓规则&#xff0c;是指描述报文匹配条件的判断语句&#xff0c;这些条件可以是报文的源地址、目的地址、端口号等。 ACL本质上是一种报文过滤器&…

Android 高通Camera2 Camera Device Close

1、很多人看到这个日志第一感觉可能觉得哪里没有合理释放&#xff0c;于是带着这个思路去进行百度探索 2、一开始我去寻找 ImageReader.OnImageAvailableListener 这个问题 var afterBitmap: Bitmap? null/**监听拍照的图片 */private val imageAvailableListener ImageRead…

GPT免费网站分享(持续更新)

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

从二叉查找树到B*树,一文搞懂搜索树的演进!|金三银四系列

对于准备面试这篇再适合不过了&#xff01;详细讲解了从BST、AVL、红黑树、B树、B树最后到B*树的演进过程&#xff0c;以及各种结构的优劣。点击上方“后端开发技术”&#xff0c;选择“设为星标” &#xff0c;优质资源及时送达在面试中&#xff0c;面试官很容易抛出这样的问题…

Java设计模式-2、⼯⼚模式

⼯⼚模式 工厂模式是对简单工厂的一个衍生&#xff0c;解决了许多简单工厂模式的问题。 一、说⼀说简单⼯⼚模式 简单⼯⼚模式指由⼀个⼯⼚对象来创建实例&#xff0c;客户端不需要关注创建逻 辑&#xff0c;只需提供传⼊⼯⼚的参数。 适⽤于⼯⼚类负责创建对象较少的情况&a…

wait讲解

hello啊,今天为大家带来wait的相关介绍 开始正题之前,我们要先进行一点知识点的补充 上一期我们更新了一期关于线程安全的知识,对于volatile在这里在做出一些补充 有些文章上说线程修改一个变量的时候,从主内存读取到工作内存上,在工作内存上修改完以后再返回主内存 由于t1线程…

[数据库原理与应用]educoder-MySQL 单表查询(一)

目录 第1关&#xff1a;用like匹配字符串 第2关&#xff1a;用BETWEEN AND表达查询范围 第3关&#xff1a;空值的判断 第4关&#xff1a;集合运算符IN的应用 第5关&#xff1a;消除重复结果 第6关&#xff1a;聚合函数应用 第7关&#xff1a;分组查询 第8关&#xf…

基于GPT3.5实现本地知识库解决方案-利用向量数据库和GPT向量接口-实现智能回复并限制ChatGPT回答的范围...

标题有点长&#xff0c;但是基本也说明出了这篇文章的主旨&#xff0c;那就是利用GPT AI智能回答自己设置好的问题 既能实现自己的AI知识库机器人&#xff0c;又能节省ChatGPT调用的token成本费用。 代码仓库地址 document.ai: 基于GPT3.5的通用本地知识库解决方案 下面图片是整…

【数据分析实战】基于python对Airbnb房源进行数据分析

文章目录&#x1f4da;引言&#x1f4d6;数据加载以及基本观察&#x1f4c3;缺失值观察及处理&#x1f516;缺失值观察以及可视化&#x1f516;缺失值处理&#x1f4c3;异常值观察及处理&#x1f4d6;数据探索&#x1f4a1;哪个区域的房源最受欢迎&#xff1f;&#x1f4a1;哪种…

完全二叉树的4种遍历方式

一张二叉树的图 1&#xff0c;二叉树的特点 每个点p的左儿子是p*2,右儿子是p*21&#xff0c;可以分别表示为p<<1与p<<1|1节点的序号是从左到右&#xff0c;从上到下增加的每个点至多2个儿子&#xff08;屁话&#xff08;bushi&#xff09;&#xff09; 2&#xff…

C语言自定义数据类型(六)使用枚举类型

目录 一、定义 二、详解 三、举例说明 一、定义 如果一个变量只有几种可能的值&#xff0c;则可以定义为枚举 (enumeration) 类型&#xff0c;所谓 “ 枚举 ” 就是指把可能的值一一列举出来&#xff0c;变量的值只限于列举出来的值的范围内。 声明枚举类型用 enum 开头。…

UR5 D-H信息 | UR5结构图 | UR5连杆名关节名 | UR5模型信息 | UR5 UDFR信息

这个问题遇到好多次了&#xff0c;不管是仿真还是可视化&#xff0c;都需要我清楚的掌握ur5的URDF信息。但是看官网的Ur5.urdf真的是看的迷迷糊糊的&#xff0c;总是无法把ur5机器人的某个部位和她的名字对应起来。之前都搞不太明白&#xff0c;今天好好整理一下&#xff0c;分…