首页 > 其他分享 >如何手写一个SpringBoot框架

如何手写一个SpringBoot框架

时间:2024-09-21 19:21:51浏览次数:12  
标签:SpringBoot Tomcat class 框架 context new 手写 public

在这篇文章中,我们将手写模拟SpringBoot的核心流程,让大家能够以一种简单的方式了解SpringBoot的大概工作原理。

项目结构

我们创建一个工程,包含两个模块:

  1. springboot模块,表示SpringBoot框架的源码实现。

  2. user包,表示用户业务系统,用来写业务代码来测试我们所模拟出来的SpringBoot。

首先,在springboot模块中添加以下依赖:

<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>

user模块下,我们进行正常的开发,比如先添加SpringBoot依赖,然后定义相关的ControllerService

<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>springboot</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

定义UserController和UserService

user包下定义UserControllerUserService,希望能通过运行MyApplication中的main方法,直接启动项目,并能在浏览器中正常访问到UserController中的某个方法。

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("test")
    public String test(){
        return userService.test();
    }
}

核心注解和核心类:

  • @SpringBootApplication:这个注解加在应用启动类上,即main方法所在的类。

  • SpringApplication:这个类中有个run()方法,用来启动SpringBoot应用。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Configuration
@ComponentScan
public @interface BobSpringBootApplication {
}

public class BobSpringApplication {

    public static void run(Class clazz){
        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
        applicationContext.register(clazz);
        applicationContext.refresh();

        startTomcat(applicationContext);
    }

    private static void startTomcat(WebApplicationContext applicationContext) {
        Tomcat tomcat = new Tomcat();

Server server = tomcat.getServer();
Service service = server.findService("Tomcat");

Connector connector = new Connector();
connector.setPort(8081);

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);

        Tomcat.addServlet(context, "dispatcher", new DispatcherServlet(applicationContext));
        context.addServletMappingDecoded("/", "dispatcher");

        try {
            tomcat.start();
        } catch (LifecycleException e) {
            e.printStackTrace();
        }

        tomcat.getServer().await();
    }
}

@BobSpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        BobSpringApplication.run(MyApplication.class);
    }
}

实现Tomcat和Jetty的切换

如果项目中有Tomcat的依赖,那就启动Tomcat;如果有Jetty的依赖就启动Jetty;如果两者都没有则报错;如果两者都有也报错。

public interface WebServer {
    void start();
}

public class TomcatWebServer implements WebServer {
    @Override
    public void start() {
        System.out.println("启动Tomcat");
    }
}

public class JettyWebServer implements WebServer {
    @Override
    public void start() {
        System.out.println("启动Jetty");
    }
}

模拟实现条件注解:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(BobOnClassCondition.class)
public @interface BobConditionalOnClass {
    String value() default "";
}

public class BobOnClassCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(BobConditionalOnClass.class.getName());
        String className = (String) annotationAttributes.get("value");

        try {
            context.getClassLoader().loadClass(className);
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }
}

模拟实现自动配置类:

@Configuration
public class WebServiceAutoConfiguration {
    @Bean
    @BobConditionalOnClass("org.apache.catalina.startup.Tomcat")
    public TomcatWebServer tomcatWebServer() {
        return new TomcatWebServer();
    }

    @Bean
    @BobConditionalOnClass("org.eclipse.jetty.server.Server")
    public JettyWebServer jettyWebServer() {
        return new JettyWebServer();
    }
}

BobSpringApplication中添加获取WebServer的方法:

public static WebServer getWebServer(ApplicationContext applicationContext) {
    Map<String, WebServer> webServers = applicationContext.getBeansOfType(WebServer.class);

    if (webServers.isEmpty()) {
        throw new NullPointerException();
    }
    if (webServers.size() > 1) {
        throw new IllegalStateException();
    }

    return webServers.values().stream().findFirst().get();
}

通过以上步骤,我们实现了一个简单的SpringBoot,并且可以根据依赖切换Tomcat和Jetty。

标签:SpringBoot,Tomcat,class,框架,context,new,手写,public
From: https://blog.csdn.net/2401_87311930/article/details/142370069

相关文章

  • 框架、工具包、插件、第三方库他们之间的区别和联系
    框架、工具包、插件和第三方库在软件开发中都是重要的组成部分,它们各自有着不同的定义、功能和用途,同时又相互联系。以下是对它们的详细解释以及区别和联系:框架(Framework)定义:框架是一种抽象的软件结构,它为特定类型的应用程序提供了基础架构和一套预定义的规则、组件及工......
  • 基于 Qwen2.5-Coder 模型和 CrewAI 多智能体框架,实现智能编程系统的实战教程
    9月19日,阿里开源了Qwen2.5系列大模型全家桶:除常规的语言模型Qwen2.5之外,还发布了专门针对编程的Qwen2.5-Coder模型和数学的Qwen2.5-Math模型,并且针对每个模型都提供了不同规模参数版本,包括:Qwen2.5语音模型:0.5B,1.5B,3B,7B,14B,32B和72BQwen2.5-Coder编程模......
  • springboot+vue在线动漫信息平台【开题+程序+论文】
    系统程序文件列表开题报告内容研究背景随着互联网的飞速发展,动漫文化在全球范围内迅速普及,成为年轻人娱乐与社交的重要载体。传统动漫传播方式受限于时间与空间,已难以满足日益增长的动漫爱好者需求。在线动漫信息平台作为连接创作者与观众的桥梁,不仅能够提供丰富多样的动漫......
  • springboot+vue自行车租赁管理系统【开题+程序+论文】
    系统程序文件列表开题报告内容研究背景随着城市化进程的加速和环保意识的提升,自行车作为绿色出行方式,其租赁服务在近年来得到了迅猛发展。传统的自行车租赁方式存在管理效率低下、信息不透明、用户体验不佳等问题,已难以满足现代都市人便捷、高效、环保的出行需求。因此,开发......
  • springboot+vue幼儿园管理系统【开题+程序+论文】
    系统程序文件列表开题报告内容研究背景随着教育信息化的不断深入,幼儿园作为儿童成长启蒙的重要阶段,其管理模式的现代化与智能化已成为必然趋势。传统的幼儿园管理方式往往依赖于纸质记录和人工操作,不仅效率低下,还容易出错,难以满足当前家长对幼儿教育透明化、个性化、高质量......
  • 医院预约|基于springBoot的医院预约挂号系统设计与实现(附项目源码+论文+数据库)
    私信或留言即免费送开题报告和任务书(可指定任意题目)目录一、摘要二、相关技术三、系统设计四、数据库设计   五、核心代码  六、论文参考 七、源码获取 一、摘要近年来,信息化管理行业的不断兴起,使得人们的日常生活越来越离不开计算机和互联网技术。首先,根据......
  • 智能仓库|基于springBoot的智能无人仓库管理设计与实现(附项目源码+论文+数据库)
    私信或留言即免费送开题报告和任务书(可指定任意题目)目录一、摘要二、相关技术三、系统设计四、数据库设计  五、核心代码  六、论文参考 七、源码获取  一、摘要互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都......
  • 基于Node.js+vue基于springboot的电商后台管理系统(开题+程序+论文) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展和电子商务行业的蓬勃兴起,电商企业面临着前所未有的机遇与挑战。为了提升运营效率、优化客户体验并增强市场竞争力,电商企业亟需构......
  • 基于Node.js+vue基于springboot的美食分享网站(开题+程序+论文) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景在数字化时代,互联网已成为人们获取信息、分享生活的重要平台。随着人们对生活品质的追求日益提升,美食文化逐渐成为大众关注的焦点。然而,传统的美食传播方式......
  • 基于Node.js+vue基于SpringBoot的小区入住管理系统(开题+程序+论文) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着城市化进程的加速,住宅小区作为城市居民生活的重要载体,其管理效率与服务质量直接关系到居民的生活品质与幸福感。传统的小区管理方式往往依赖于人工记录......