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

文章目录

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

1.创建maven项目
2.使用Git管理项目(可以略过)
1.创建一个github存储库
2.克隆到本地,复制文件夹的内容
3.粘贴到idea项目文件夹,将其作为本地仓库与远程仓库关联
3.pom.xml 引入父工程和场景启动器
  • 其实父工程只是指定了引入依赖的默认版本
  • 真正的依赖是场景启动器来引入的
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.编写运行类
java 复制代码
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怎么启动的?

2.@Configuration机制梳理

1.环境搭建
1.文件目录
2.Dog.java
java 复制代码
package com.sun.springboot.bean;

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

}
3.Config.java 注入单例Dog对象
java 复制代码
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
java 复制代码
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.成功获取
2.机制分析
1.简述
2.图解

3.SpringBoot是怎么启动Tomcat的?

1.环境搭建
1.文件目录
2.HiController.java
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.测试访问
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
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>
            <!--  因为要手动创建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.文件目录
2.创建Tomcat对象,关联Spring容器并启动
java 复制代码
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
java 复制代码
package com.sun.sunspringboot;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class SunMainApp {
    public static void main(String[] args) {
        SunSpringApplication.run();
    }
}
4.结果展示
2.创建Spring容器
1.文件目录
2.Monster.java
java 复制代码
package com.sun.sunspringboot.bean;

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

}
3.SunConfig.java
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
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.文件目录
2.编写SunWebApplicationInitializer的onStartup方法
  • 在Tomcat启动的时候会调用onStartup方法
  • 首先注册配置类,然后将中央控制器放到 servletContext
java 复制代码
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的上下文路径
4.启动测试
1.报错
2.引入对应版本的jasper包即可
xml 复制代码
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>8.5.75</version>
        </dependency>
3.重新启动
4.访问测试,成功返回结果
相关推荐
青&棠28 分钟前
JDK 多版本管理工具 jvms
java
FITA阿泽要努力33 分钟前
Agent Engineer-Day 1 初始智能体与大语言模型基础
java·前端·javascript
2601_9498683635 分钟前
Flutter for OpenHarmony 电子合同签署App实战 - 数据持久化实现
java·数据库·flutter
金牌归来发现妻女流落街头37 分钟前
【Spring Boot注解】
后端·springboot
码农阿豪41 分钟前
基于Milvus与混合检索的云厂商文档智能问答系统:Java SpringBoot全栈实现
java·spring boot·milvus
阿蒙Amon43 分钟前
C#每日面试题-Task和Thread的区别
java·面试·c#
无心水1 小时前
数据库字符串类型详解:VARCHAR、VARCHAR2、CHARACTER VARYING的区别与选择指南
数据库·后端·varchar·varchar2·character·字符串类型·2025博客之星
索荣荣1 小时前
Java异步编程终极实战指南
java·开发语言
shehuiyuelaiyuehao1 小时前
11String类型知识点
java·开发语言
毕设源码-赖学姐1 小时前
【开题答辩全过程】以 基于Java的图书馆座位预约管理系统设计为例,包含答辩的问题和答案
java·开发语言