自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我們一起聊聊如何手寫一個(gè)SpringBoot框架

開發(fā) 前端
在這篇文章中,我們將手寫模擬SpringBoot的核心流程,讓大家能夠以一種簡單的方式了解SpringBoot的大概工作原理。

你好,我是柳岸花開。

在這篇文章中,我們將手寫模擬SpringBoot的核心流程,讓大家能夠以一種簡單的方式了解SpringBoot的大概工作原理。

項(xiàng)目結(jié)構(gòu)

我們創(chuàng)建一個(gè)工程,包含兩個(gè)模塊:

  1. springboot模塊,表示SpringBoot框架的源碼實(shí)現(xiàn)。
  2. user包,表示用戶業(yè)務(wù)系統(tǒng),用來寫業(yè)務(wù)代碼來測試我們所模擬出來的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模塊下,我們進(jìn)行正常的開發(fā),比如先添加SpringBoot依賴,然后定義相關(guān)的Controller和Service:

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

定義UserController和UserService

在user包下定義UserController和UserService,希望能通過運(yùn)行MyApplication中的main方法,直接啟動項(xiàng)目,并能在瀏覽器中正常訪問到UserController中的某個(gè)方法。

@RestController
public class UserController {

    @Autowired
    private UserService userService;

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

核心注解和核心類:

  • @SpringBootApplication:這個(gè)注解加在應(yīng)用啟動類上,即main方法所在的類。
  • SpringApplication:這個(gè)類中有個(gè)run()方法,用來啟動SpringBoot應(yīng)用。
@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);
    }
}

實(shí)現(xiàn)Tomcat和Jetty的切換

如果項(xiàng)目中有Tomcat的依賴,那就啟動Tomcat;如果有Jetty的依賴就啟動Jetty;如果兩者都沒有則報(bào)錯(cuò);如果兩者都有也報(bào)錯(cuò)。

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

模擬實(shí)現(xiàn)條件注解:

@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;
        }
    }
}

模擬實(shí)現(xiàn)自動配置類:

@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();
}

通過以上步驟,我們實(shí)現(xiàn)了一個(gè)簡單的SpringBoot,并且可以根據(jù)依賴切換Tomcat和Jetty。

責(zé)任編輯:武曉燕 來源: 柳岸花開
相關(guān)推薦

2024-06-17 11:59:39

2022-06-26 09:40:55

Django框架服務(wù)

2025-02-28 08:46:24

框架微服務(wù)架構(gòu)

2024-07-03 08:36:14

序列化算法設(shè)計(jì)模式

2023-08-04 08:20:56

DockerfileDocker工具

2022-05-24 08:21:16

數(shù)據(jù)安全API

2023-08-10 08:28:46

網(wǎng)絡(luò)編程通信

2023-09-10 21:42:31

2023-06-30 08:18:51

敏捷開發(fā)模式

2021-08-27 07:06:10

IOJava抽象

2024-02-20 21:34:16

循環(huán)GolangGo

2023-04-03 00:09:13

2024-09-09 00:00:00

編寫技術(shù)文檔

2024-09-30 09:33:31

2024-11-27 16:07:45

2024-09-04 08:55:56

2021-10-14 11:08:17

大數(shù)據(jù)框架內(nèi)存

2022-02-23 08:41:58

NATIPv4IPv6

2022-09-22 08:06:29

計(jì)算機(jī)平板微信

2024-07-26 09:47:28

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號