如何描述Springboot启动过程?
2 个回答
上了生活的贼船,就要做快乐的海盗。白紫琪Spring Boot 的启动过程实际上是一个由多步骤构成的复杂流程,但为了便于理解,我会通过通俗易懂的方式一步步解释它的核心部分。 ### 1. **启动类的 `main` 方法** Spring Boot 应用的启动从一个普通的 Java `main` 方法开始。在你创建的 Spring Boot 项目中,通常有一个主类,这个主类带有 `@SpringBootApplication` 注解,并包含一个 `main` 方法。这个 `main` 方法会调用 `SpringApplication.run()` 来启动整个应用。 ```java @SpringBootApplication public class MySpringBootApplication { public static void main(String[] args) { SpringApplication.run(MySpringBootApplication.class, args); } } ``` ### 2. **`@SpringBootApplication` 注解** `@SpringBootApplication` 是一个复合注解,它包含了几个重要的注解,主要包括: - **`@SpringBootConfiguration`**:相当于 `@Configuration`,表示这是一个配置类。 - **`@EnableAutoConfiguration`**:这个注解告诉 Spring Boot 启动时,应该基于类路径下的依赖自动配置 Spring 应用上下文。 - **`@ComponentScan`**:Spring Boot 会扫描带有 `@Component`、`@Service`、`@Repository`、`@Controller` 等注解的类,自动注册到 Spring 容器中。 ### 3. **SpringApplication 类** `SpringApplication.run()` 是 Spring Boot 启动的关键方法,它会启动 Spring 应用。这个类做了以下几件重要的事: 1. **创建 SpringApplication 对象**: - Spring Boot 会创建一个 `SpringApplication` 实例,初始化各种启动设置。包括找到应用运行的环境(开发环境还是生产环境)、设置 Banner 等信息。 2. **准备环境(Environment)**: - Spring Boot 会根据配置文件(如 `application.properties` 或 `application.yml`)加载环境配置,如端口号、数据库配置等。还会检查系统变量、JVM 参数等。 3. **设置应用类型**: - `SpringApplication` 会判断应用是 Web 应用还是普通应用(非 Web 应用)。比如,如果你在类路径上有 `spring-boot-starter-web` 依赖,它会自动认为你要启动一个 Web 应用。 4. **启动监听器(Listeners)**: - Spring Boot 启动时会触发一些事件(比如启动事件、环境准备事件等),这些事件会通知相应的监听器,监听器可以做一些额外的操作。 ### 4. **创建并刷新 Spring 容器(ApplicationContext)** Spring Boot 会根据应用类型选择不同的 **ApplicationContext**,这是 Spring 应用上下文的核心,它管理了所有 Bean 的生命周期和依赖注入。 - **加载 Bean 定义**:Spring Boot 会扫描项目中的 Bean,并根据 `@ComponentScan` 注解找到需要加载的 Bean。 - **自动配置**:根据类路径上的依赖(例如,如果你有 `spring-boot-starter-data-jpa`,它会自动配置数据源和 JPA),Spring Boot 自动配置合适的 Bean。 - **Bean 创建与依赖注入**:Spring Boot 会创建这些 Bean 并将它们注入到其他依赖的地方,所有的 Bean 都在 ApplicationContext 中进行管理。 ### 5. **初始化 Web 容器(如 Tomcat)** 如果你启动的是一个 Web 应用,Spring Boot 会内嵌一个 Web 服务器(默认是 Tomcat)。它会启动 Tomcat 并在指定端口上监听请求。 - **配置 Web 环境**:Spring Boot 会自动配置嵌入式的 Tomcat 或 Jetty,并将应用上下文绑定到 Web 容器上。 - **DispatcherServlet**:对于 Web 应用来说,Spring Boot 会配置 `DispatcherServlet` 作为核心,负责将 HTTP 请求路由到对应的控制器。 ### 6. **执行 `CommandLineRunners` 和 `ApplicationRunners`** 在 Spring Boot 启动完成后,如果你有实现 `CommandLineRunner` 或 `ApplicationRunner` 接口的 Bean,它们会被自动执行。这通常用于在应用启动后执行一些初始化任务。 ### 7. **应用启动完成** 到这一步,Spring Boot 应用已经完成了启动过程,并开始处理请求或执行其他任务。你会看到控制台输出启动的日志,包括启动端口和应用的关键信息。 ### Spring Boot 启动过程总结: 1. **启动 `main` 方法**,调用 `SpringApplication.run()`。 2. **解析 `@SpringBootApplication`**,启动自动配置和组件扫描。 3. **创建 `SpringApplication` 对象**,准备环境和配置。 4. **加载并刷新 Spring 容器(ApplicationContext)**,找到所有 Bean 并自动配置。 5. **启动 Web 容器**(如 Tomcat,针对 Web 应用),配置 HTTP 请求处理。 6. **执行 `CommandLineRunner` 和 `ApplicationRunner`** 进行自定义初始化逻辑。 7. **启动完成**,应用开始处理请求或执行任务。 通俗地说,Spring Boot 就像是启动一个"大工厂"的过程,`SpringApplication.run()` 是启动按钮,`ApplicationContext` 是这个工厂的核心管理者,自动配置会为工厂的不同部门配置合适的机器设备,最后一切就绪后,工厂开始正常运转。编辑于 2024-10-28 22:40 •IP属地 美国举报评论收藏
自己喜欢的东西,就不要问别人好不好。粑粑### 构造SpringApplication实例 1.首先会调用SpringApplication的静态方法run(),在这个方法里面会调用构造器方法创建出一个SpringApplication实例,在构造器中会确定当前web应用类型,是reactive web类型,还是servlet web类型,还是none类型。以及设置监听器等等,完成一些初始化操作。(监听器就是来监听SpringApplication启动过程的,在开始启动,创建上下文,启动失败等生命周期事件时都会调用监听器相关的方法) ### 执行run()方法 2.然后去执行实例的run()方法,首先会创建一个StopWatch计时器器,来统计run()方法的启动耗时,在日志里面会显示启动时间,那个时间就是在这里统计的。然后处理环境参数,就是java -jar ***.jar启动命令中带的那些jvm参数。  ### 创建applicationContext 3.会创建出一个ApplicationContext,一般servlet的应用的context类型是AnnotationConfigServletWebServerApplicationContext。(可以认为beanFactory就是ioc容器,但是我们一般不直接使用beanFactory获取bean,而是通过applicationContext来获取,ioc容器beanFactory是应用上下文applicationContext的一个属性,applicationContext也实现了BeanFactory接口,可以认为applicationContext是一个高级容器,applicationContext支持国际化,默认是启动时加载所有bean,而不是用到时才进行懒加载,以及支持事件机制。) ### 执行prepareContext()方法 4.然后会调用prepareContext()方法来为应用上下文做一些准备工作,会将运行时的参数封装成bean,注册到beanFactory中去,以及使用load方法加载启动类。 ### 执行refreshContext()方法 5.在这里会启动容器,也就是会为beanFactory做很多配置,注册BeanPostProcessors,设置类加载器等等。在这一步也会解析启动类中@SpringBootApplication这个组合注解。 ### afterRefresh()方法 6.这个方法里面会把容器里面所有ApplicationRunner自定义子类和CommandLineRunner自定义子类的Bean全部取出来,执行它们的run()方法。(就是有时候如果需要在应用启动后执行一些我们自定义的初始化操作,可以通过自定义一个类,继承ApplicationRunner类来实现。) 之后会调用listeners.started()方法,通知所有Listener,application已经启动完成了,以及调用listeners.running()方法通知所有Listener,application已经运行了。 ```java //系统启动完可以做一些业务操作 @Component //如果有多个runner需要指定一些顺序 @Order(1) public class SimosApplicationRunner implements ApplicationRunner { @Autowired SystemInitService systemInitService; @Override public void run(ApplicationArguments args) throws Exception { systemInitService.systemInit(); } } ``` [https://my.oschina.net/funcy/blog/4873261](https://my.oschina.net/funcy/blog/4873261) [https://www.imooc.com/article/264722](https://www.imooc.com/article/264722)编辑于 2022-02-26 19:39 •IP属地 河北举报评论收藏1
公众号进入网站体验更佳

