参考:
- rhyme : SPRINGBOOT启动流程及其原理
- fhfirehuo: SpringBoot的启动流程
- 只会一点java : spring boot容器启动详解
- 二月_春风 :EnableAutoConfiguration注解的工作原理
- Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等;但他们的基础都是Spring 的ioc和 aop,ioc 提供了依赖注入的容器, aop解决了面向切面编程,然后在此两者的基础上实现了其他延伸产品的高级功能。
- Spring MVC提供了一种轻度耦合的方式来开发web应用;它是Spring的一个模块,是一个web框架;通过DispatcherServlet, ModelAndView 和 View Resolver,开发web应用变得很容易;解决的问题领域是网站应用程序或者服务开发——URL路由、Session、模板引擎、静态Web资源等等。
- Spring Boot实现了auto-configuration自动配置(另外三大神器actuator监控,cli命令行接口,starter依赖),降低了项目搭建的复杂度。它主要是为了解决使用Spring框架需要进行大量的配置太麻烦的问题,所以它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具;同时它集成了大量常用的第三方库配置(例如Jackson, JDBC, Mongo, Redis, Mail等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用(out-of-the-box)。
在其中比较重要的有三个注解,它们三个可以用一个 @SpringBootApplication 替代:
- @SpringBootConfiguration:继承了Configuration,表示当前是注解类
- @EnableAutoConfiguration :启用或禁用 Spring Boot 自动配置。
- @ComponentScan:定义 Bean 扫描范围,加载到IOC容器。
例如,这两个代码块都会导致类似的行为:
@EnableAutoConfiguration 原理
EnableAutoConfiguration注解的工作原理
SpringApplication 构造方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.sources = new LinkedHashSet(); this.bannerMode = Mode.CONSOLE; this.logStartupInfo = true; this.addCommandLineProperties = true; this.addConversionService = true; this.headless = true; this.registerShutdownHook = true; this.additionalProfiles = new HashSet(); this.isCustomEnvironment = false; this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null");
// 主启动类,放到 Set 里。其实就是一个有 @SpringbootApplication 的启动类 this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
// 确定项目的启动类型。springboot1.5 只有两种类型web环境和非web环境,springboot2.0 有三种类型:
// 1.NONE:不需要在web容器环境下运行,也就是普通的工程
// 2.SERVLET:基于Servlet的WEB项目
// 3.Reactive:响应式Web应用,Spring5版本的新特性 this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 实例化所有实现了 org.springframework.context.ApplicationContextInitializer 接口的类(主要方法 initialize) this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 实例化所有实现了 org.springframework.context.ApplicationListener 接口的类(主要方法 onApplicationEvent) this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
// main 函数所在的启动类 this.mainApplicationClass = this.deduceMainApplicationClass(); }
两个值得注意的地方,实例化了所有 ApplicationContextInitialzer 和 ApplicationListener
- org.springframework.context.ApplicationContextInitializer#initialize
- 会在 ConfigurableApplicationContext 的 refresh() 方法调用之前被调用(prepareContext方法中调用),做一些容器的初始化工作。
- org.springframework.context.ApplicationListener#onApplicationEvent
- Springboot整个生命周期在完成一些阶段的时候都会通过事件推送器(EventPublishingRunListener)产生一个事件(ApplicationEvent), 然后再遍历每个监听器(ApplicationListener)以匹配事件对象,这是一种典型的观察者设计模式。
这些可以在 META-INF/spring.factories 文件中进行自定义,代码中通过 getSpringFactoriesInstances方法获取,这种机制叫做 SPI机制:定义一个服务接口,这个接口的多个实现通过本地的配置文件获取到类名再通过反射进行实例化,轻松可插拔。
spring-boot 的 META/spring.factories 里本来也有一些已经定义好的:
ApplicationListener
我们来大概的看下ApplicationListener的一些实现类以及他们具体的功能简介
事件推送机制(观察者模式)
它们都实现了接口
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { void onApplicationEvent(E var1); }
这些 Listener 会在 SpringApplication.run() 方法的不同阶段通过事件机制触发
例如 下面这两个 Listener
class ClearCachesApplicationListener implements ApplicationListener<ContextRefreshedEvent> { //....... }
public class FileEncodingApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered { //..... }
启动方法 SpringApplication.run() 内,环境信息准备好后
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { //...... listeners.environmentPrepared((ConfigurableEnvironment)environment); //...... }
listeners 是 SpringApplicationRunListener 的所有实现类。主要是 EventPublishingRunListener,还有个 SpringContextRunListener 不知道干嘛的。
在 SpringApplication 类的构造方法里从 sping.factories 里实例化的所有的 Listener 类都在 EventPublishingRunListener 的 SpringApplication 里。
class SpringApplicationRunListeners { private final List<SpringApplicationRunListener> listeners; //...... public void starting() { Iterator var1 = this.listeners.iterator(); while(var1.hasNext()) { SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next(); listener.starting(); } } public void environmentPrepared(ConfigurableEnvironment environment) { Iterator var2 = this.listeners.iterator(); while(var2.hasNext()) { SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next(); listener.environmentPrepared(environment); } } public void contextPrepared(ConfigurableApplicationContext context) { Iterator var2 = this.listeners.iterator(); while(var2.hasNext()) { SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next(); listener.contextPrepared(context); } }
//......
}
在 SpringApplication 类的构造方法里从 sping.factories 里实例化的所有的 Listener 类都在 EventPublishingRunListener 的 SpringApplication 里。
可以看到,不同的发布方法(starting, enviromentPrepared, contextPrepared),会发布对应的不同的事件类型(ApplicationEvent 的不同子类)
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered { private final SpringApplication application; private final String[] args; private final SimpleApplicationEventMulticaster initialMulticaster; //...... public void starting() { this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args)); } public void environmentPrepared(ConfigurableEnvironment environment) { this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment)); } public void contextPrepared(ConfigurableApplicationContext context) { this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context)); } //....... }
这里会根据不同的 ApplicationEvent 筛选出对应的一些 Listener ,然后逐个调用它们的 onApplicationEvent 方法
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster { //....... public void multicastEvent(ApplicationEvent event) { this.multicastEvent(event, this.resolveDefaultEventType(event)); } public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event); Executor executor = this.getTaskExecutor(); // 这里根据不同的 ApplicationEvent 即 事件类型 筛选 监听了相应事件的 Listeners。判断是否支持事件。 Iterator var5 = this.getApplicationListeners(event, type).iterator(); // 逐个调用筛选后的 Listener 的 onApplicationEvent 方法 while(var5.hasNext()) { ApplicationListener<?> listener = (ApplicationListener)var5.next(); if (executor != null) { executor.execute(() -> { this.invokeListener(listener, event); }); } else { this.invokeListener(listener, event); } } } //....... }
SpringApplication.run() 方法
- starting(ApplicationStartingEvent) 在SpringApplication启动时就调用
- environmentPrepared(ApplicationEnvironmentPreparedEvent) 在environment准备好时调用
- contextPrepared(ApplicationContextInitializedEvent) context初始化后调用
- contextLoaded(ApplicationPreparedEvent) 加载了bean资源后发出该事件。
- started(ApplicationStartedEvent) 刷新了context后发出的事件。
- running(ApplicationReadyEvent) 调用完ApplicationRunner和CommandLineRunner后发出的事件。
- failed(ApplicationFailedEvent) 在启动时发生异常会发出该事件。
源码