SpringBoot 启动分析 序列文章基于 spring-boot-starter-parent 1.5.19.RELEASE 。
启动一个 SpringBoot 应用只需要下面几行代码即可:
@SpringBootApplication public class SpringBootDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringBootDemoApplication.class, args); } }
查看 SpringApplication.run
方法时会来到:
public static ConfigurableApplicationContext run(Object source, String... args) { return run(new Object[] { source }, args); } public static ConfigurableApplicationContext run(Object[] sources, String[] args) { return new SpringApplication(sources).run(args); }
可以看到 SpringBoot 的魔法就是那么简单: 创建一个 SpringApplication,执行其 run 方法 。
就像 “打开冰箱门、把大象塞进冰箱、关上冰箱门” 那么简单、有力。
当然,要了解原理是不能只看高层抽象的。
SpringFactoriesLoader 是 Spring 提供的 SPI 实现机制,从类路径下的 META-INF/spring.factories
文件里加载指定接口的所有实现。以接口的完整类名作为 key,实现类的完整名字作为值,多个实现类用 ,
分隔。
下面是 spring-boot-autoconfigure 包下 META-INF/spring.factories
文件里的 一小部分:
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=/ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,/ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,/ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,/ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,/ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,/ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,/ org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,/
SpringFactoriesLoader 内部通过 ClassLoader.getResources
方法来加载类路径下的文件。
SpringBoot 利用事件与监听器来简化启动主流程的逻辑。
SpringApplicationRunListeners
:持有一组 SpringApplicationRunListener
的引用,用于批量通知 SpringApplicationRunListener
。
SpringApplicationRunListener
:用于监听 SpringApplication
. run
方法的执行,有5个回调方法:
started
:run方法执行的时候立马执行;对应事件的类型 是ApplicationStartedEvent
。 environmentPrepared
: ApplicationContext
创建之前并且环境信息准备好的时候调用;对应事件的类型是 ApplicationEnvironmentPreparedEvent
。 contextPrepared
: ApplicationContext
创建好并且在source加载之前调用一次;没有具体的对应事件。 contextLoaded
: ApplicationContext
创建并加载之后并在refresh之前调用;对应事件的类型是 ApplicationPreparedEvent
。 finished
:run方法结束之前调用;对应事件的类型是 ApplicationReadyEvent
或 ApplicationFailedEvent
。 ApplicationListener
:应用事件监听器。
事件广播关系:
SpringApplicationRunListeners --> SpringApplicationRunListener(EventPublishingRunListener) --> ApplicationEventMulticaster(SimpleApplicationEventMulticaster) --> ApplicationListener
下面是从运行时的角度看ApplicationContext 的重要组件及扩展机制,而非源码组织的角度。
Environment
:由下面两个组成。
application-${profile}.properties
,用在 Bean 上一般是 @Profile({"p1", "!p2"})}
表示 p1
激活或 p2
不激活时启用。一个 Bean 如果没有声明 profile 则表示默认是激活的,配置文件名上不带 profile 信息则表示是默认的配置。 PropertySource
里, PropertySources
持有一个或多个 PropertySource
。 BeanFactory
:Bean工厂,可以进行 Bean定义注册、实例化 Bean、对外提供获取 Bean 实例的功能。一般还持有一个对父 BeanFactory
的引用。当获取一个Bean时,如果当前工厂不存在给定BeanName的Bean定义,则尝试从父 BeanFactory
获取。
BeanFactoryPostProcessor
:用于定制化修改上下文底层 BeanFactory 里的 Bean 定义和适配 Bean 属性的值。该接口只有一个方法 void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
。
BeanDefinitionRegistryPostProcessor
继承自
BeanFactoryPostProcessor
,并在 BeanFactoryPostProcessor
被应用之前先应用,用于注册更多的 Bean。有一个新增的方法 void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
。
BeanPostProcessor
:一种扩展机制,包含两个方法,用于对创建的 Bean 进行增强,AOP就是在这个机制实现类里实现的。
Object postProcessBeforeInitialization(Object bean, String beanName) `Object postProcessAfterInitialization(Object bean, String beanName)
EnvironmentPostProcessor
: Environment
后置处理器,由 ConfigFileApplicationListener.onApplicationEnvironmentPreparedEvent
触发执行,具体的实现类有:
同一类组件的不同实现的执行顺序是有一定规则的
ConfigurationClassParser
:它的 processConfigurationClass
方法递归地解析 @Configuration
配置类,SpringBoot 的 auto-configure 机制就是在这个阶段被解析到上下文里的。
@PropertySource @ComponentScan @Import @ImportResource @Bean
ConfigurationClassBeanDefinitionReader
:把 ConfigurationClassParser
解析得到的 Bean 定义 注册到 BeanDefinitionRegistry
。
ConfigurationClassPostProcessor
:借助 ConfigurationClassParser
和 ConfigurationClassParser
递归地解析配置类并注册到 BeanDefinitionRegistry
。
ConditionEvaluator
:根据 @Conditional
注解进行评估一个 Bean 定义是否应该注册。
ConfigurableEnvironment
,广播 ApplicationEnvironmentPreparedEvent
事件, ConfigFileApplicationListener
收到通知后利用 SPI 机制加载所有 EnvironmentPostProcessor
的实现类,触发其 postProcessEnvironment
方法。 ConfigFileApplicationListener
自身也实现了 EnvironmentPostProcessor
接口,在它的 postProcessEnvironment
里通过内部类 Loader 加载所有的配置文件,并处理 profile,最终所有键值对都被添加到 Environment 里。 AnnotationConfigApplicationContext
,实例化的过程中会把 应用指定的启动配置类、 ConfigurationClassPostProcessor
实例注册到底层的 BeanFacotry 实例里。 ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry
注册所有的 Bean 定义。 BeanPostProcessor
进行加工增强,得到最终的 Bean object 给应用使用。 欢迎关注我的微信公众号: coderbee笔记 ,可以更及时回复你的讨论。