手写模拟SpringBoot核心流程(一):实现极简一个SpringBoot——模拟SpringBoot启动过程

前言

Spring Boot 是一个开源的框架,用于简化 Spring 应用程序的开发和部署。它建立在 Spring Framework 的基础上,内置了web服务器——tomcat和jetty,使得 Spring 应用的构建变得更加快速、简单和可维护。

本文通过实现一个SpringBoot,学习SpringBoot是如何进行工作的。

创建两个模块

实现SpringBoot-模块.png

  • springboot:模拟实现springboot框架
  • user:测试调用实现的springboot架构的用户业务系统

引入依赖包

  • SpringBoot基于Spring架构,需要在springboot模块中依赖Spring
  • SpringBoot也支持Spring MVC功能,依赖Spring MVC和Tomcat等

在SpringBoot模块中要添加以下依赖。

<?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">  
    <parent>  
        <artifactId>simulate-springboot</artifactId>  
        <groupId>org.example</groupId>  
        <version>1.0-SNAPSHOT</version>  
    </parent>  
    <modelVersion>4.0.0</modelVersion>  
  
    <artifactId>springboot</artifactId>  
  
    <properties>  
        <maven.compiler.source>8</maven.compiler.source>  
        <maven.compiler.target>8</maven.compiler.target>  
    </properties>  
  
    <dependencies>  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-context</artifactId> 
            <version>5.3.18</version>  
        </dependency>  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-web</artifactId>  
            <version>5.3.18</version>  
        </dependency>  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-webmvc</artifactId>  
            <version>5.3.18</version>  
        </dependency>  
        <dependency>  
            <groupId>javax.servlet</groupId>  
            <artifactId>javax.servlet-api</artifactId>  
            <version>4.0.1</version>  
        </dependency>  
        <dependency>  
            <groupId>org.apache.tomcat.embed</groupId>  
            <artifactId>tomcat-embed-core</artifactId>  
            <version>9.0.60</version>  
        </dependency>  
    </dependencies>  
  
</project>

对于user模块,添加springboot模块即可

<?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">  
    <parent>  
        <artifactId>simulate-springboot</artifactId>  
        <groupId>org.example</groupId>  
        <version>1.0-SNAPSHOT</version>  
    </parent>  
    <modelVersion>4.0.0</modelVersion>  
  
    <artifactId>user</artifactId>  
  
    <properties>  
        <maven.compiler.source>8</maven.compiler.source>  
        <maven.compiler.target>8</maven.compiler.target>  
    </properties>  
  
    <dependencies>  
        <dependency>  
            <groupId>org.example</groupId>  
            <artifactId>springboot</artifactId>  
            <version>1.0-SNAPSHOT</version>  
        </dependency>  
    </dependencies>  
  
</project>

实现SpringBoot简单功能

以下代码若无特别说明则均在springboot模块中,具体位置请查看项目文件结构。

@BerSpringBootApplication注解

package com.ber.springboot;  
  
import org.springframework.context.annotation.ComponentScan;  
import org.springframework.context.annotation.Configuration;  
  
import java.lang.annotation.ElementType;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;  
import java.lang.annotation.Target;  
  
/**  
 * @Author 鳄鱼儿  
 * @Description TODO  
 * @date 2023/8/19 14:05  
 * @Version 1.0  
 */
@Target(ElementType.TYPE)  
@Retention(RetentionPolicy.RUNTIME)  
@Configuration  
@ComponentScan  
public @interface BerSpringBootApplication {  
}

BerSpringApplication启动类

package com.ber.springboot;  
  
import org.apache.catalina.*;  
import org.apache.catalina.connector.Connector;  
import org.apache.catalina.core.StandardContext;  
import org.apache.catalina.core.StandardEngine;  
import org.apache.catalina.core.StandardHost;  
import org.apache.catalina.startup.Tomcat;  
import org.springframework.web.context.WebApplicationContext;  
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;  
import org.springframework.web.servlet.DispatcherServlet;  
  
/**  
 * @Author 鳄鱼儿  
 * @Description TODO  
 * @date 2023/8/19 14:08  
 * @Version 1.0  
 */  
public class BerSpringApplication {  
    public static void run(Class clazz) {  
        // 1. 创建Spring 容器  
        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();  
        applicationContext.register(clazz);  
        applicationContext.refresh();  
  
        // 2. 创建并启动Tomcat  
        startTomcat(applicationContext);  
    }  
  
    private static void startTomcat(WebApplicationContext applicationContext) {  
        // 2.1 创建tomcat对象  
        Tomcat tomcat = new Tomcat();  
  
        Server server = tomcat.getServer();  
        Service service = server.findService("Tomcat");  
  
        Connector connector = new Connector();  
        // 设置默认tomcat启动端口  
        connector.setPort(8023);  
  
        Engine engine = new StandardEngine();  
        engine.setDefaultHost("localhost");  
  
        Host host = new StandardHost();  
        host.setName("localhost");  
  
        String contextPath = "";  
        Context context = new StandardContext();  
        context.setPath(contextPath);  
        context.addLifecycleListener(new Tomcat.FixContextListener());  
  
        host.addChild(context);  
        engine.addChild(host);  
  
        service.setContainer(engine);  
        service.addConnector(connector);  
  
        // 2.2 创建DispatcherServlet对象,并与Spring容器绑定,并将DispatcherServlet对象添加至Tomcat中  
        tomcat.addServlet(contextPath, "dispatcher", new DispatcherServlet(applicationContext));  
        context.addServletMappingDecoded("/*", "dispatcher");  
  
        // 2.3 启动tomcat  
        try {  
            tomcat.start();  
        } catch (LifecycleException e) {  
            e.printStackTrace();  
        }  
    }  
}

run方法实现

user模块中Controller方法被浏览器请求时,就需要run方法去启动一个tomcat,并需要通过一个Servlet接收所有的请求,并将请求分发给相应的Controller进行处理。

在Spring MVC中,DispatcherServlet就起到这个前端控制器的作用。DispatcherServlet需要绑定一个Spring容器,当DispatcherServlet接收到请求后,就可以从绑定的Spring容器中找到所匹配的Controller,并执行对应的方法。

因此,在run方法中实现了:

  1. 创建一个Spring容器
  2. 创建并启动Tomcat
    1. 创建tomcat对象
    2. 创建DispatcherServlet对象,并与Spring容器绑定,并将DispatcherServlet对象添加至Tomcat中
    3. 启动Tomcat
创建spring容器

创建了一个AnnotationConfigApplicationContext容器,并通过传入的clazz作为容器的配置类。

那么,是如何将clazz作为配置类的呢?

在user模块中,UserApplication启动类是这样的。

package com.ber.user;  
  
import com.ber.springboot.BerSpringApplication;  
import com.ber.springboot.BerSpringBootApplication;  
  
/**  
 * @Author 鳄鱼儿  
 * @Description TODO  
 * @date 2023/8/19 14:10  
 * @Version 1.0  
 */  
@BerSpringBootApplication  
public class UserApplication {  
  
    public static void main(String[] args) {  
        BerSpringApplication.run(UserApplication.class);  
    }  
}

将UserApplication.class传入run方法,UserApplication类就是AnnotationConfigWebApplicationContext容器的配置类。

配置过程为:
SpringBoot的run方法配置类过程.png

在Spring容器AnnotationConfigWebApplicationContext创建好后,该容器内部就拥有了user模块下启动类所在包路径下的Bean。

创建并启动Tomcat

在startTomcat()方法中,创建了tomcat对象,并对tomcat进行配置,如默认端口8023,创建和配置 Tomcat 引擎和主机等。然后再创建DispatcherServlet对象,并与Spring容器绑定,并将DispatcherServlet对象添加至Tomcat中。

当运行user模块的UserApplication启动类时,调用BerSpringApplication类中的run方法,所以在run方法中调用startTomcat()方法。

到此,就可以试着运行BerSpringBoot了,可以看到已经成功启动tomcat,并成功访问到了
http://localhost:8023/test

极简SpringBoot实现效果.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鳄鱼儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值