目录
Springboot启动流程
核心代码
验证效果
Springboot启动流程
- 创建Spring容器, 扫描并启动
- 容器选择Tomcat/Jetty
- 创建DispatchServlet, 与spring容器绑定
- 将DispatchServlet添加到Tomcat
- 启动Tomcat
核心代码
1. 首先, 创建两个module
2. maven依赖
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模块依赖
<dependency>
<groupId>org.example</groupId>
<artifactId>springboot</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- <exclusions>
<exclusion>
<artifactId>tomcat-embed-core</artifactId>
<groupId>org.apache.tomcat.embed</groupId>
</exclusion>
</exclusions>-->
</dependency>
<!-- 切换netty-->
<!-- <dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.43.v20210629</version>
</dependency>-->
3. springboot核心配置类
public class KkSpringApplication {
/*
1. 创建Spring容器
2. 创建Tomcat
3. 创建DispatchServlet, 与spring容器绑定
4. 将DispatchServlet添加到Tomcat
5. 启动Tomcat
*/
public static void run(Class clazz) {
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(clazz);
applicationContext.refresh();
WebServer webServer = getWebServer(applicationContext);
webServer.start(applicationContext);
}
private static WebServer getWebServer(AnnotationConfigWebApplicationContext applicationContext) {
Map<String, WebServer> map = applicationContext.getBeansOfType(WebServer.class);
if (map.isEmpty()) {
throw new NullPointerException();
}
if (map.size() > 1) {
throw new IllegalStateException();
}
return map.values().stream().findFirst().get();
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Configuration
@ComponentScan
@Import(KkImportSeclet.class)
public @interface KkSpringBootApplication {
}
4. Import自动配置类
public class KkImportSeclet implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 自动配置
ServiceLoader<AutoConfiguration> loader = ServiceLoader.load(AutoConfiguration.class);
List<String> list = new ArrayList<>();
for (AutoConfiguration configuration : loader) {
list.add(configuration.getClass().getName());
}
return list.toArray(new String[0]);
}
}
@Configuration
public class WebServerAutoConfiguration implements AutoConfiguration{
@Bean
@ConditionalOnClass("org.apache.catalina.startup.Tomcat")
public TomcatWebServer tomcatWebServer(){
return new TomcatWebServer();
}
@Bean
@ConditionalOnClass("org.eclipse.jetty.server.Server")
public JettyWebServer jettyWebServer(){
return new JettyWebServer();
}
}
public interface AutoConfiguration {
}
spi注入自动配置类. 资源目录创建文件
5. 条件注解
public class KkCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionalOnClass.class.getName());
String className = (String) annotationAttributes.get("value");
try {
context.getClassLoader().loadClass(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Conditional(KkCondition.class)
public @interface ConditionalOnClass {
String value();
}
6. Tomcat启动类实现
public class TomcatWebServer implements WebServer{
@Override
public void start(AnnotationConfigWebApplicationContext 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(contextPath, "dispatcher", new DispatcherServlet(applicationContext));
context.addServletMappingDecoded("/*", "dispatcher");
try {
tomcat.start();
} catch (LifecycleException e) {
e.printStackTrace();
}
System.out.println("启动Tomcat ... ");
}
}
7. User模块使用自定义springboot组件
@KkSpringBootApplication
public class MyApplication {
public static void main(String[] args) {
KkSpringApplication.run(MyApplication.class);
}
}
验证效果
1. 启动MyApplication
2. 调test接口文章来源:https://www.toymoban.com/news/detail-790501.html
文章来源地址https://www.toymoban.com/news/detail-790501.html
到了这里,关于手写Springboot核心流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!