本文主要是介绍SpringBoot通过main方法启动web项目实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《SpringBoot通过main方法启动web项目实践》SpringBoot通过SpringApplication.run()启动Web项目,自动推断应用类型,加载初始化器与监听器,配置Spring...
Spring Boot 通过 main
方法启动 Web 项目的过程涉及多个核心组件和自动化机制,下面从源码角度详细拆解:
1. 启动入口:SpringApplication.run()
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
SpringApplication.run()
是启动的核心入口,它主要完成以下工作:
2. SpringApplication初始化
// SpringApplication 构造函数核心逻辑 public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { // 1. 设置资源加载器 this.resourceLoader = resourceLoadphper; // 2. 校验并保存主配置类(即 @SpringBootApplication 标注的类) this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); // 3. 推断应用类型(REACTIVE、SERVLET、NONE) this.webApplicationType = WebApplicationType.deduceFromClasspath(); China编程 // 4. 加载并实例化 ApplicationContextInitializer setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 5. 加载并实例化 ApplicationListener setListeners((Collection) getSpringFactoriesInstancjses(ApplicationListener.class)); // 6. 推断 main 方法所在类 this.mainApplicationClass = deduceMainApplicationClass(); }
关键步骤:
- 应用类型推断:通过检查类路径中是否存在
org.springframework.web.reactive.DispatcherHandler
(REACTIVE)或Javax.servlet.Servlet
(SERVLET)来确定应用类型。 - 初始化器(Initializer):从
META-INF/spring.factories
加载ApplicationContextInitializer
,用于在ApplicationContext
刷新前自定义配置。 - 监听器(Listener):加载
ApplicationListener
,监听启动过程中的事件(如ApplicationStartingEvent
)。
3. run()方法核心流程
public ConfigurableApplicationContext run(String... args) { // 1. 计时和发布启动事件 StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); // 2. 获取并启动监听器 SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { // 3. 构建应用参数和环境配置 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); // 4. 创建并配置 ApplicationContext context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); // 5. 准备上下文(加载 Bean 定义) prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 6. 刷新上下文(核心启动逻辑) refreshContext(context); // 7. 刷新后的回调处理 afterRefresh(context, applicationArguments); // 8. 发布应用就绪事件 listeners.started(context); // 9. 执行 Runner(如 CommandLineRunner) callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); } // 10. 发布应用运行中事件 listeners.running(context); return context; }
4. 嵌入式 Web 服务器启动关键点
4.1refreshContext()方法触发服务器启动
private void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } } protected void refresh(ConfigurableApplicationContext context) { // 调用 AbstractApplicationContext 的 refresh() 方法 context.refresh(); }
4.2ServletWebServerApplicationContext的核心作用
对于 Web 应用,ApplicationContext
实际类型为 AnnotationConfigServletWebServerApplicationContext
,它继承自 ServletWebServerApplicationContext
,后者在 refresh()
过程中会:
// ServletWebServerApplicationContext 核心方法 @Override protected void onRefresh() { super.onRefresh(); try { // 创建并启动嵌入式 Web 服务器 createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start web server", ex); } } private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null) { // 1. 获取 ServletWebServerFactory(如 TomcatServletWebServerFactory) ServletWebServerFactory factory = getWebServerFactory(); // 2. 创建并配置 Web 服务器 this.webServer = factory.getWebServer(getSelfInitializer()); } else if (servletContext != null) { try { getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context", ex); } } initPropertySources(); }
4.3ServletWebServerFactory实例化服务器
以 Tomcat 为例,TomcatServletWebServerFactory
的 getWebServer()
方法会:
@Override public WebServer getWebServer(ServletContextInitializer... initializers) { // 1. 创建 Tomcat 实例 Tomcat tomcat = new Tomcat(); // 2. 配置服务器基本参数(端口、上下文路径等) File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat"); tomcat.setBaseDir(baseDir.getAbsolutePath()); Connector connector = new Connector(this.protocol); tomcat.getService().addConnector(connector); custwww.chinasem.cnomizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); // 3. 配置 ServletContextInitializer(如 DispatcherServlet) prepareContext(tomcat.getHost(), initializers); // 4. 启动服务器 return getTomcatWebServer(tomcat); }
5. Spring MVC 组件自动配置
通过 WebMvcAutoConfiguration
自动配置核心组件:
DispatcherServlet
:作为前端控制器,处理所有 HTTP 请求。HandlerMapping
:映射 URL 到具体的 Controller 方法。ViewResolver
:解析视图名称到实际视图。
关键代码(WebMvcAutoConfiguration
):
@Bean @Primary @ConditionalOnMissingBean(DispatcherServlet.class) public DispatcherServlet dispatcherServlet(WebMvcProperties properties) { DispatcherServlet dispatcherServlet = new DispatcherServlet(); dispatcherServlet.setDispatchOptionsRequest(properties.isDispatchOptionsRequest()); dispatcherServlet.setDispatchTraceRequest(properties.isDispatchTraceRequest()); dispatcherServlet.setThrowExceptionIfNoHandlerFound(properties.isThrowExceptionIfNoHandlerFound()); dispatcherServlet.setPublishEvents(properties.isPublishRequestHandledEvents()); dispatcherServlet.setEnableLoggingRequestDetails(properties.isLogRequestDetails()); return dispatcherServlet; }
6. 最终启动结果
- 嵌入式服务器(如 Tomcat)启动并监听指定端口(默认 8080)。
DispatcherServlet
注册到 Servlet 容器,作为所有请求的入口。- Spring 上下文初始化完成,所有 Bean 已加载并可用。
ApplicationReadyEvent
发布,标志应用可处理外部请求。
总结:启动流程关键点
SpringApplication
初始化:推断应用类型、加载初始化器和监听器。- 环境配置:加载
application.properties
等配置源。 ApplicationContext
创建:根据 Web 类型选择相应的上下文实现。- 自动配置:基于依赖和条件注解,自动配置 Web 组件(如
DispatcherServlet
)。 - 嵌入式服务器启动:通过
ServletWebServerFactory
创建并启动 Tomcat/Jetty。 - Spring MVC 初始化:配置请求映射、视图解析等核心组件。
通过这种机制,Spring Boot 实现了“零配置”启动 Web 项目的能力,开发者只需关注业务逻辑,无需手动处理服务器配置和组件装配。
这篇关于SpringBoot通过main方法启动web项目实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!