SpringBoot系列-启动原理(上)
SpringBoot-启动原理(上)
概要
Spring Boot是建立在Spring框架之上的微服务框架,旨在简化Spring应用的开发过程。与传统的Spring应用相比,Spring Boot采用约定优于配置的原则,通过提供默认配置和快速开发的特性,大大减少了开发者的工作量。Spring Boot还支持快速构建独立的、可执行的JAR包,使得应用的部署变得更加简单。
springboot的启动经过了一些一系列的处理,我们先看看整体过程的流程图:
一、@SpringBootApplication 注解
@SpringBootApplication 注解是Spring Boot的核心注解,它其实是一个组合注解。在某个类上面使用该注解,说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用。
注解定义如下:
1 @Target(ElementType.TYPE) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Inherited 5 @SpringBootConfiguration 6 @EnableAutoConfiguration 7 @ComponentScan(excludeFilters = { 8 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), 9 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) 10 public @interface SpringBootApplication { 11 //...... 12 }
1. @SpringBootConfiguration
允许在上下文中注册额外的 bean 或导入其他配置类
@SpringBootConfiguration 是一个特殊的 @Configuration,用于标识 Spring Boot 的配置类。
2. @EnableAutoConfiguration(开启自动配置)
@EnableAutoConfiguration 是实现自动装配的核心注解,自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector类。
@EnableAutoConfiguration 告诉 Spring Boot 根据类路径中的 jar 依赖,为项目进行自动配置。它会扫描类路径下的 META-INF/spring.factories 文件,并根据其中定义的自动配置类进行配置。
3. @ComponentScan(开启自动扫描)
@ComponentScan 启用组件扫描,使 Spring 能够扫描当前包及其子包中的 Spring 组件并将其注册到 Spring 容器中。
扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描启动类所在的包下所有的类 ,可以自定义不扫描某些 bean。如下图所示,容器中将排除TypeExcludeFilter和AutoConfigurationExcludeFilter。
二、SpringApplication.run() 启动流程
可以肯定的是,所有的标准的SpringBoot的应用程序都是从run方法开始的。
1 @SpringBootApplication 2 public class Application { 3 4 public static void main(String[] args) { 5 SpringApplication.run(Application.class,args); 6 } 7 }
先附上这个方法的完整代码,通过注释可以知道这个方法的作用就是创建和刷新一个新的ApplicationContext,也就是Springboot的上下文bean容器
源码如下:
1 public ConfigurableApplicationContext run(String... args) { 2 // 开始执行,记录开始时间 3 long startTime = System.nanoTime(); 4 DefaultBootstrapContext bootstrapContext = this.createBootstrapContext(); 5 ConfigurableApplicationContext context = null; 6 7 // 设置系统属性 java.awt.headless 的值,默认为true 8 this.configureHeadlessProperty(); 9 10 // 创建所有 Spring 运行监听器 11 // 从META-INF/spring.factories中获取并启动监听器 12 // 获取SpringApplicationRunListeners,内部只有一个EventPublishingRunListener 13 SpringApplicationRunListeners listeners = this.getRunListeners(args); 14 15 // 会封装成SpringApplicationEvent事件然后广播出去给SpringApplication中的listeners所监听 16 // 这里接受ApplicationStartedEvent事件的listener会执行相应操作 17 listeners.starting(bootstrapContext, this.mainApplicationClass); 18 19 try { 20 // 处理 args 参数 21 // 创建ApplicationArguments 对象 初始化默认应用参数类 22 // args是启动Spring应用的命令行参数,该参数可以在Spring应用中被访问。如:--server.port=9000 23 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); 24 25 // 准备环境 26 // 项目运行环境Environment的预配置 27 // 创建并配置当前SpringBoot应用将要使用的Environment 28 // 并遍历调用所有的SpringApplicationRunListener的environmentPrepared()方法 29 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments); 30 this.configureIgnoreBeanInfo(environment); 31 32 // 创建 Banner 的打印类 33 Banner printedBanner = this.printBanner(environment); 34 35 // 创建Spring容器,即创建应用上下文 36 // 根据应用程序的类型,创建相应的ApplicationContext实例 37 context = this.createApplicationContext(); 38 context.setApplicationStartup(this.applicationStartup); 39 40 // 准备应用上下文 41 // Spring容器前置处理 42 // 这一步主要是在容器刷新之前的准备动作。包含一个非常关键的操作:将启动类注入容器,为后续开启自动化配置奠定基础。 43 // 把所有需要管理的 Bean 统计出来 44 this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 调用Spring的refresh方法 45 this.refreshContext(context); 46 47 48 // 应用上下文刷新之后的事件的处理 49 // 扩展接口,设计模式中的模板方法,默认为空实现。 50 // 如果有自定义需求,可以重写该方法。比如打印一些启动结束log,或者一些其它后置处理 51 this.afterRefresh(context, applicationArguments); 52 Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime); 53 if (this.logStartupInfo) { 54 (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup); 55 } 56 57 // 广播出ApplicationReadyEvent事件给相应的监听器执行 58 // 发布应用上下文启动完成事件 59 listeners.started(context, timeTakenToStartup); 60 61 // 执行所有 Runner 运行器 62 // 用于调用项目中自定义的执行器XxxRunner类,使得在项目启动完成后立即执行一些特定程序 63 // Runner 运行器用于在服务启动时进行一些业务初始化操作,这些操作只在服务启动后执行一次。 64 // Spring Boot提供了ApplicationRunner和CommandLineRunner两种服务接口 65 this.callRunners(context, applicationArguments); 66 } catch (Throwable var12) { 67 // 过程报错的话会执行一些异常操作 68 // 然后广播出ApplicationFailedEvent事件给相应的监听器执行 69 this.handleRunFailure(context, var12, listeners); 70 throw new IllegalStateException(var12); 71 } 72 73 try { 74 Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime); 75 76 // 发布应用上下文准备就绪事件 77 listeners.ready(context, timeTakenToReady); 78 79 // 返回Spring容器 80 return context; 81 } catch (Throwable var11) { 82 this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null); 83 throw new IllegalStateException(var11); 84 } 85 }
参考链接:
https://www.cnblogs.com/imreW/p/17398305.html