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.访问测试,成功返回结果
相关推荐
凡人的AI工具箱15 分钟前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
陈王卜18 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、18 分钟前
Spring Boot 注解
java·spring boot
午觉千万别睡过21 分钟前
RuoYI分页不准确问题解决
spring boot
java亮小白199723 分钟前
Spring循环依赖如何解决的?
java·后端·spring
飞滕人生TYF29 分钟前
java Queue 详解
java·队列
2301_8112743140 分钟前
大数据基于Spring Boot的化妆品推荐系统的设计与实现
大数据·spring boot·后端
武子康1 小时前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康1 小时前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
苏-言1 小时前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring