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.访问测试,成功返回结果
相关推荐
逊嘘6 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
morris13113 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
monkey_meng31 分钟前
【Rust中的迭代器】
开发语言·后端·rust
余衫马33 分钟前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng37 分钟前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
七星静香38 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员39 分钟前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU39 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie643 分钟前
在IDEA中使用Git
java·git
Elaine2023911 小时前
06 网络编程基础
java·网络