spring boot的启动过程?
3 个回答
生活就是这样,别人看到的是结果,而自己撑的是整个过程。Hobbit霍比特人### Spring Boot的启动过程 Spring Boot的启动过程主要分为以下几个步骤: 1. **main 函数入口**: - Java程序从启动主类的`main()`方法开始执行。 ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 2. **加载 Spring 上下文**: - 调用`SpringApplication.run()`方法,实例化一个`SpringApplication`对象并调用其`run`方法。 ```java public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { return new SpringApplication(primarySource).run(args); } ``` ```java public ConfigurableApplicationContext run(String... args) { // 创建并配置环境 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); // 创建上下文实例 context = createApplicationContext(); // 准备上下文 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 刷新上下文 refreshContext(context); // 调用所有的 runner callRunners(context, applicationArguments); return context; } ``` 3. **加载并初始化各种 bean**: - 在`prepareContext`和`refreshContext`方法中,Spring Boot会完成Bean的加载和初始化。 ```java private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { context.setEnvironment(environment); postProcessApplicationContext(context); applyInitializers(context); listeners.contextPrepared(context); ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); } load(context, getAllSources().toArray(new Object[0])); listeners.contextLoaded(context); } ``` ```java public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } } ``` 4. **启动 embedded 的服务器(如果是 web 项目)**: - 根据classpath中是否包含特定的类来判断是否为web项目,如果是web项目,则启动嵌入式的服务器(如Tomcat)。 ```java private void refreshContext(ConfigurableApplicationContext context) { if (context instanceof AbstractApplicationContext) { ((AbstractApplicationContext) context).refresh(); } } ``` ```java public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } } ``` 通过以上步骤,Spring Boot启动并初始化Spring上下文和各种Bean,如果是Web项目,还会启动嵌入式服务器。编辑于 2023-12-16 14:03 •IP属地 辽宁举报评论收藏
明知不可为而为之就是我最大的诚意夜太### Spring Boot的启动过程 下图展示了Spring Boot的整个启动流程及各组件的相互调用关系:  Spring Boot的启动过程主要分为以下几个步骤: 1. **调用主类的main()方法开始**: - Java程序由启动主类调用`main()`方法开始。 2. **实例化SpringApplication对象**: - 调用`SpringApplication`的构造方法,实例化一个Spring应用对象。在构造方法里主要完成启动环境的初始化工作,例如推断主类、Spring应用类型、加载配置文件、读取`spring.factories`文件等。 3. **调用run方法**: - 所有的启动工作在`run`方法内完成,主要完成加载配置资源、准备上下文、创建上下文、刷新上下文和发布事件等。 ### 1. 启动入口(SpringApplication) Spring Boot的启动类通过`@SpringBootApplication`注解和`psvm`(`main`方法)启动: ```java @SpringBootApplication public class SummaryApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(SummaryApplication.class); application.run(args); // SpringApplication.run(SummaryApplication.class, args); 也可以简化调用静态方法 } } ``` #### 1.1 @SpringBootApplication注解 `@SpringBootApplication`注解是`@Configuration`,`@EnableAutoConfiguration`和`@ComponentScan`三个注解的组合。 ```java @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { } ``` ##### 1.1.1 @SpringBootConfiguration 该注解就是Spring IoC容器中Java config配置方式的`@Configuration`,注册当前类为Spring IoC容器的配置类。 ##### 1.1.2 @EnableAutoConfiguration `@EnableAutoConfiguration`借助`@Import`的帮助,将所有符合自动配置条件的bean定义加载到IoC容器。 ##### 1.1.3 @ComponentScan `@ComponentScan`注解在Spring中用于自动扫描并加载符合条件的组件或bean定义,最终将这些bean定义加载到IoC容器中。 ### 2. 构造器(Constructor) ```java public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); this.webApplicationType = WebApplicationType.deduceFromClasspath(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); } ``` ### 3. 启动方法(RUN) `run`方法完成了所有Spring的整个启动过程: ```java public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); } listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; } ``` #### 3.1 SpringApplicationRunListener 的使用 通过`getSpringFactoriesInstances`获取到所有实现`SpringApplicationRunListener`接口的实例,默认情况下该接口的实现类只有`EventPublishingRunListener`。 #### 3.2 prepareEnvironment 创建和配置`ConfigurableEnvironment`,将所有配置参数填充到环境对象中,并发布事件。 #### 3.3 创建SpringApplicationContext 上下文 根据Web容器类型的不同创建不同的上下文实例。 #### 3.4 上下文初始化 ```java private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { context.setEnvironment(environment); postProcessApplicationContext(context); applyInitializers(context); listeners.contextPrepared(context); if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } Set<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[0])); listeners.contextLoaded(context); } ``` ### 3.5 刷新上下文 `AbstractApplicationContext`的`refresh`方法: ```java public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } } ``` 至此,Spring Boot的启动主要工作基本完成,接下来发布`AppStartedEvent`事件,回调`ApplicationRunner`,`CommandLineRunner`等runner,发布`applicationReadyEvent`事件,Spring Boot正式启动开始运行。编辑于 2023-11-28 07:02 •IP属地 西藏举报评论收藏
用眼睛是看不到事物的本质的,只有心灵才能够洞察一切。hello发布于 2022-12-09 16:04 •IP属地 甘肃举报评论收藏
公众号进入网站体验更佳

