三公机器人

牛牛机器人,三公撑船机器人,微信牛牛机器人

用300行代码手写SpringBoot核心原理(一)

一、核心注解定义

SpringBoot的"约定优于配置"核心依赖注解实现,我们先定义核心注解:

import java.lang.annotation.*;

// 组合注解,替代@Configuration+@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@MyConfiguration
@EnableMyAutoConfiguration
public @interface MySpringBootApplication {
   String scanBasePackages() default "";
}

// 配置类注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyConfiguration {
   boolean proxyBeanMethods() default true;
}

// 开启自动配置
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MyAutoConfigurationImportSelector.class)
public @interface EnableMyAutoConfiguration {
}

// 自动配置类注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@MyConfiguration(proxyBeanMethods = false)
public @interface MyAutoConfiguration {
}

// 条件注解:存在指定类时生效
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConditionalOnClass {
   String[] value() default {};
}

// 条件注解:不存在指定Bean时生效
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConditionalOnMissingBean {
   Class<?>[] value() default {};
}

二、自动配置导入选择器

实现ImportSelector接口,加载自动配置类:

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class MyAutoConfigurationImportSelector implements ImportSelector {
   private static final String AUTO_CONFIGURATION_FILE =
       "META-INF/myspringboot/autoconfigure.imports";

   @Override
   public String[] selectImports(AnnotationMetadata importingClassMetadata) {
       List<String> configurations = new ArrayList<>();
       
       // 读取自动配置文件
       try (BufferedReader reader = new BufferedReader(
           new InputStreamReader(
               getClass().getClassLoader().getResourceAsStream(AUTO_CONFIGURATION_FILE)
           )
       )) {
           String line;
           while ((line = reader.readLine()) != null) {
               line = line.trim();
               if (!line.isEmpty() && !line.startsWith("#")) {
                   configurations.add(line);
               }
           }
       } catch (IOException e) {
           throw new RuntimeException("Failed to load auto-configuration classes", e);
       }
       
       return configurations.toArray(new String);
   }
}

三、条件评估器

实现条件注解的评估逻辑:

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Map;

public class OnClassCondition implements Condition {
   @Override
   public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
       Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnClass.class.getName());
       if (attributes == null) {
           return false;
       }
       
       String[] classNames = (String[]) attributes.get("value");
       for (String className : classNames) {
           try {
               context.getClassLoader().loadClass(className);
           } catch (ClassNotFoundException e) {
               return false;
           }
       }
       return true;
   }
}

public class OnMissingBeanCondition implements Condition {
   @Override
   public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
       Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnMissingBean.class.getName());
       if (attributes == null) {
           return false;
       }
       
       Class<?>[] beanTypes = (Class<?>[]) attributes.get("value");
       for (Class<?> beanType : beanTypes) {
           if (context.getBeanFactory().containsBean(beanType.getName())) {
               return false;
           }
       }
       return true;
   }
}

四、示例自动配置类

创建一个模拟的Web自动配置类:

@MyAutoConfiguration
@ConditionalOnClass("javax.servlet.Servlet")
public class WebAutoConfiguration {

   @Bean
   @ConditionalOnMissingBean
   public MyDispatcherServlet dispatcherServlet() {
       return new MyDispatcherServlet();
   }

   @Bean
   @ConditionalOnMissingBean
   public MyTomcatWebServer tomcatWebServer(MyDispatcherServlet dispatcherServlet) {
       return new MyTomcatWebServer(dispatcherServlet);
   }
}

五、嵌入式Web服务器实现

模拟Tomcat服务器的核心逻辑:

public class MyTomcatWebServer {
   private final MyDispatcherServlet dispatcherServlet;

   public MyTomcatWebServer(MyDispatcherServlet dispatcherServlet) {
       this.dispatcherServlet = dispatcherServlet;
   }

   public void start() {
       System.out.println("启动嵌入式Tomcat服务器,端口:8080");
       System.out.println("注册DispatcherServlet处理请求");
       // 实际Tomcat初始化逻辑简化
   }
}

public class MyDispatcherServlet {
   public void service(String request, String response) {
       System.out.println("DispatcherServlet处理请求:" + request);
       // 请求分发逻辑简化
   }
}

六、SpringBoot应用启动类

实现核心启动逻辑:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MySpringApplication {
   public static void run(Class<?> primarySource, String... args) {
       AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
       
       // 注册主配置类
       context.register(primarySource);
       
       // 刷新容器
       context.refresh();
       
       // 启动Web服务器
       startWebServer(context);
       
       System.out.println("MySpringBoot应用启动完成!");
   }

   private static void startWebServer(AnnotationConfigApplicationContext context) {
       MyTomcatWebServer webServer = context.getBean(MyTomcatWebServer.class);
       if (webServer != null) {
           webServer.start();
       }
   }
}

七、测试应用

创建测试启动类和控制器:

@MySpringBootApplication
public class MyTestApplication {
   public static void main(String[] args) {
       MySpringApplication.run(MyTestApplication.class, args);
   }
}

// 控制器示例
@MyController
@RequestMapping("/hello")
public class HelloController {
   @GetMapping
   public String hello() {
       return "Hello MySpringBoot!";
   }
}

八、自动配置文件

resources/META-INF/myspringboot/autoconfigure.imports中添加:

com.example.autoconfigure.WebAutoConfiguration


Powered By Z-BlogPHP 1.7.3

三公机器人,牛牛机器人,三公撑船机器人,微信牛牛机器人