Spring Boot启动
- 关键类、方法:ConfigurableApplicationContext SpringApplication#run。
new SpringApplication(primarySources).run(args);
类方法说明
- SpringApplication类
可以被用来从Java主方法中引导、启动一个Spring应用的类。默认,类会执行下面步骤来引导你的应用:- 创建一个合适的ApplicationContext实例(依赖你的类路径)。
- 注册一个CommandLinePropertySource来暴露命令行参数为Spring属性。
- 刷新应用上下位,加载所有的单例bean。
- 触发任意的CommandLinerRunner bean。
在多数情况下,静态run(Class, String[])可以直接从你的main方法调用,来引导你的应用。
对于更高级的配置,SpringApplication实例可以在被运行前创建和自定义:
SpringApplication application = new SpringApplication(MyApplication.class);
//...在这里自定义应用设置
application.run(args);
SpringApplication可以从各种源中读取bean。通常建议@Configuration来引导你的应用,然而,你也可能从下面方式中设置getSources():
1. 由AnnotatedBeanDefinitionReader加载的全限定类名
2. 由XmlBeanDefinitionReader加载的XML资源位置,或者由GroovyBeanDefinitionReader加载的groovy脚本
3. ClassPathBeanDefinitionScanner扫描的包名
配置属性也被绑定到SpringApplication。这让动态设置SpringApplication属性成为可能,像额外的源("spring.main.sources",一个CSV列表)标志来表示web环境("spring.main.web-application-type=none")或者关闭横幅的("spring.main.banner-mode=off")。
- 方法SpringApplication(ResourceLoader resourceLoader, Class>... primarySources)
创建一个新的SpringApplication实例。应用上下文会从指定主要源加载bean(看SpringApplication类级别文档。实例可以在调用run(String...)之前自定义)。 - 方法Collection
getSpringFactoriesInstance(Class type, Class>[] paramenterTypes, Object... args) - ResourceLoader接口
加载资源的策略接口(例如,类路径或者文件系统资源)。org.springframework.context.ApplicationContext被要求提供这个功能,延申扩展org.springframework.core.io.support.ResourcePatternResolver支持。
DefaultResourceLoader是一个独立实现,在ApplicationContext外是可用的,也被ResourceEditor使用。
Resource类型的bean属性和Resource数组可以从字符串中填充,当运行在ApplicationContext中时,使用特殊的上下文资源加载策略。 - Resource getResource(String location):为给定的资源位置返回一个Resource处理。该处理应该总是可以重复使用的资源描述符,允许多次Resource#getInputStream()调用。
- 必须支持全限定URL,例如,"file:C:/test.dat"
- 必须支持类路径伪限定URL,例如, "classpath:test.dat"
- 应该支持相对路径,例如, "WEB-INF/test.dat"。(这会被具体实现,一般由ApplicationContext实现提供)
注意,一个Resource处理不表明一个存在的资源;你需要调用Resource#exists去检查存在性。
- 类WebApplicationType
web应用可能类型的枚举:NONE、SERVLET、REACTIVE。NONE:该类型应用不应该运行为web应用,不应该启动内置web服务器;SERVLET: 该类型应用应该运行为基于servlet的web应用,应该启动内置servlet web服务器;REACTIVE:该类型应用应该运行为响应式web应用,应该启动内置响应式web服务器。 - 方法WebApplicationType deduceFromClassPath
从类路径上推断Web应用类型,SERVLET的标志类```{"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"}。默认返回SERVLET。 - 接口 ApplicationContextInitializer
初始化Spring ConfigurableApplicationContext的回调接口,优于被ConfigurableApplicationConetxt#refresh()刷新。
一般用在web应用上,就是要求应用上下文的一些编程方式的初始化。例如,根据ConfigurableApplicationContext#getEnvironment() 上下文的环境来注册属性元或者激活配置。查看ContextLoader和FrameworkServlet,支持声明一个contextInitializerClasses上下文参数和初始化参数。
ApplicationContextInitializer处理器鼓励去检查是否Spring的org.springframework.core.Ordered 接口已经被实现,或者是否org.springframework.core.annotation.Order注解是否出现,来排序实例。 - 方法void initialize(C applicationContext):初始化给定的应用上下文
- 类SpringFactoriesLoader
用在框架内部的普通目的工厂加载机制。
SpringFactoriesLoader#loadFactories加载并且实例化#FACTORIES_RESOURCE_LOCATION文件中给定类型的工厂,它们可能出现在类路径中的多个JAR文件中。spring.factories文件必须用Properties格式,在这种格式种,建时全限定的接口或者抽象类名称,值时逗号分隔的实现类名列表。例如:
example.MyService=example.MyServiceImpl1,example.MyServiceImpl2
# example.MyService时接口的名称,MyServiceImpl1和MyServiceImpl2是两个实现
- 方法List
loadFactoryNames(Class> factoryType, ClassLoader classLoader)
加载#FACTORIES_RESOURCE_LOCATION中给定的工厂实现的全限定类名,使用给定的类加载器。 - 方法loadSpringFactories
FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories",从该文件中,加载资源,解析属性,并且添加到缓存中。 - 方法createSpringFactoriesInstances
利用反射,加载、实例化上一步工厂配置中指定的名称对应的类,并添加大链表中。 - instantiateFactory
使用反射,创建工厂实现类的实例。 - 方法 setInitializers
设置将会应用到Spring ApplicationContext的ApplicationCOntextInitializer - 接口ApplicationListener
函数式接口。由应用事件监听器实现的接口。基于标准的java.util.EventListener接口,用于观察者设计模式。
在Spring 3.0时,一个ApplicationListener通常可以声明感兴趣的事件类型。当用Spring ApplicationContext注册时,事件会相应地被过滤,监听器只在匹配的事件对象被调用。 - onApplicationEvent
处理一个应用事件 - EventListener
所有事件监听器接口必须继承的标记接口 - ApplicationEvent
被所有应用事件继承的类。抽象是因为直接发布通用事件是没有意义的。 - ApplicationEventMulticaster
被可以管理许多ApplicationListener对象,并且可以发布事件给它们的对象实现的接口。
org.springframework.context.ApplicationEventPublisher,一般一个Spring org.springframework.context.ApplicationContext,可以使用ApplicationEventMulticaster作为实际发布事件的委派。 - deduceMainApplicationClass
根据执行点的StackTraceElement,栈帧来与"main"比较,判断主应用类。 - StopWatch
简单的秒表,允许许多任务的时间点,暴露总共运行事件和每个命名任务的运行事件。隐藏Sys#nanoTime()的使用,提供应用代码的可读性,减少计算错误的可能性。注意,这个对象不是设计成线程安全的,并且不使用同步。这个类通常被用于验证概念性证明工作中和开发中的性能,而不是作为生产应用的部分。在Spring Framework 5.2中,运行时被跟踪,并且以毫秒报告。 - start()
开启一个未命名的任务。如果未先调用这个方法,那么stop()或者时机方法的结果是未定义的。 - ConfigurableApplicationContext
由大多数应用上下文(如果不是所有)实现的SPI接口。
提供功能配置一个应用上下文,加上在org.springframework.context.ApplicationContext接口中的应用上下文客户端方法。配置和生命周期方法在这里封装,未了避免让它们对ApplicationContext客户端代码明显。出现的方法应该只在启动和关闭代码中使用。 - SpringBootExceptionReporter
函数式接口。用来支持SpringApplication启动错的自定义报告。SpringBootExceptionReporter通过SpringFactoriesLoader加载,并且必须声明由一个单一ConfigurableApplicationContext参数的公共构造器。 - boolean reportException
报告一个启动失败给用户 - SpringApplicationRunListeners
一组SpringApplicationRunListener。 - SpringApplicationRunListener
SpringApplication#run方法的监听器。SpringApplicationRunListener通过SpringFactoriesLoader加载,并且应该声明一个公共构造器,接收一个SpringApplication实例,和一个String[] 参数。一个新的SpringApplicationRunListener实例会为每次运行创建。 - 类ApplicationStartingEvent
尽早发布的事件,只要SpringApplication已经被启动——在Environment或者ApplicationContext可用之前,但是在ApplicationListener已经被注册后。事件源是SpringAplication自身,但是小心在早期阶段使用它的内部状态过多,因为它可能在后面的生命周期中被修改。 - 接口ConfigurableEnvironment
被多数Environment类型实现的接口。提供功能:设置激活、默认profile、操作底层属性源。允许客户端通过ConfigurablePropertyResolver超接口设置、验证要求的属性、自定义边界服务等等。
操作属性源。属性元可以被移除、重排序或者替换;并且额外的属性元可以使用MutablePropertySources实例添加,就是从getPropertySources()返回的。下面的例子依据ConfigurableEnvironment的StandardEnvironment实现,但是通常对任何实现可用,即时默认属性元可能不同。
例子:添加一个有更高搜索优先级的新属性源:
ConfigurableEnvironment environment = new StandardEnvironment();
MutablePropertySources propertySources = environment.getPropertySources();
Map myMap = new HashMap<>();
myMap.put("xyz", "myValue");
propertySources.addFirst(new MapPropertySource("My_MAP", myMap));
例子:移除默认系统属性源
MutablePropertySources propertySources = environment.getPropertySources();
propertySources.remove(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
例子:为了测试目的,模拟系统环境
MutablePropertySources propertySources = environment.getPropertySources();
MockPropertySource mockEnvVars = new MockPropertySource().withProperty("xyz", "myValue");
propertySources.replace(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
当一个Environment被ApplicationContext使用时,有一点是比较重要的,就是PropertySource操作要在上下文的org.springframework.context.support.AbstractApplicationContext#refresh()方法调用之前执行。这确保所有属性源在容器引导过程中都可用,包括通过org.springframework.context.support.PropertySourcesPlaceholderConfigurer属性占位符使用。
- prepareEnvironment
- 创建Env
- 配置Env,就是属性、profile
- 向监听器发送env准备好的事件
- 绑定env到SpringApplication
- 返回env对象
- configureIgnoreBeanInfo(COnfigurableEnvironment environment)
- createApplicationContext
根据应用类型,反射实例化上下文类:SERVLET-org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;REACTIVE-org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;default-org.springframework.context.annotation.AnnotationConfigApplicationContext - prepareContext()
- 给上下文设置env
- 后置处理应用上下文。应用任何紧密相关的后置处理ApplicationContext,如果需要,子类可以应用额外的处理:配置bean名称生成器、设置资源加载器、添加便捷服务
- 应用任何ApplicationContextInitializer到上下文,在上下文被刷新前。
- 获取初始化器。返回要被应用到Spring ApplicationContext的ApplicationContextInitializer集合
- 给监听器发送上下文已准备好事件。就是ApplicationContext已经被创建、准备好,但是在源被加载前调用
- 获取上下文内部的bean工厂,主备手动注册各种bean
- 加载源的bean到应用上下文
- 给监听器发送上下文准备好的事件。在应用上下文已经被加载,但是在应用上下文被刷新前调用。
- refreshContext()
刷新应用上下文。最后调用的是一个同步方法。一次只能有一个线程调用。刷新配置的持久化表示,可能是XML文件、属性文件或者关系型数据库 - refresh()
- prepareRefresh():为刷新准备这个上下文,设置它的启动日期和激活标志,包括执行属性源的初始化
- 设置启动日期
- 设置激活标志为true
- 初始化属性源。初始化在上下文环境中的任意占位符属性源。用实际实例替换存根属性源
- 验证所有被标记为要求的属性为可解析的:看ConfigurablePropertyResolver#setRequiredProperties
- 存储预刷新ApplicationListeners
- 允许所有早期ApplicationEvents集合,一旦广播可用就发布
- obtainFreshbeanFactory():告诉子类刷新内部bean工厂。其实就是执行真实的配置加载,返回bean工厂。
- prepareBeanFactory():准备bean工厂,在这个上下文中使用该bean工厂。就是配置该工厂的标准上下文特征,例如上下文的类加载器和后置处理器。
- postProcessBeanFactory():允许在上下文子类中bean工厂的后置处理。在bean工厂的标准初始化后,修改该应用上下文的内部bean工厂。所有bean定义会被已经加载,但是还没有bean已经被实例化。这允许在某种ApplicationContext实现中注册特殊的BeanPostProcessors等等。
- invokeBeanFactoryPostProcessors():调用在该上下文中注册为bean的工厂处理器。实例化并且调用所有注册的BeanFactoryPostProcessor bean。
- registerBeanPostProcessors():注册bean处理器,拦截bean创建
- initMessageSource():为这个上下文初始化消息源
- initApplicationEventMulticaster():为这个上下文初始化事件广播。初始化ApplicationEventMulticaster。如果在该上下文中没有定义,使用SimpleApplicationEventMulticaster。现在才注册???
- onRefresh():初始化其他在特定上下文子类中的具体bean
- registerListeners():检查监听器bean,并且注册它们
- finishBeanFactoryInitialization():初始化所有保留的(非延迟初始化)单例。完成这个上下文的bean工厂的初始化,实例化所有剩余单例bean。
- finishRefresh():发布相应的事件
- destroyBeans():销毁已经创建的单例,避免悬挂资源
- cancelRefresh():重置active标志
- resetCommonCaches():重置Spring内核中公共的内省缓存,因为我们可能不再需要单例bean的元数据。
- prepareRefresh():为刷新准备这个上下文,设置它的启动日期和激活标志,包括执行属性源的初始化
- AbstractAplicationContext类还是很重要的
- afterRefresh()
在上下文已经被刷新后调用 - stop()
停止秒表 - stated()
给监听器发送事件,就是上下文已经被刷新,并且应用已经启动,但是CommandLineRunner和ApplicationRunner还没有被调用
36.接口 ApplicationRunner
一个函数式ean包含在SpringApplication中时,它是否应该运行。多个ApplicationRunner bean可以被定义在相同的应用上下文中,并且可以用Ordered接口或者@Order排序。 - running()
在run方法完成前,立刻调用,当应用上下文已经被刷新,并且所有的CommandLineRunner和ApplicationRunner已经被调用后。