spring boot 启动过程
启动流程图
- 启动程序入口
public static void main(String[] args) {
SpringApplication.run(WebApplication02.class, args);
}
- SpringApplication run 方法
...省略部分代码
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//反射的方式加载SpringApplicationRunListeners 实例
SpringApplicationRunListeners listeners = getRunListeners(args);
// 调用监听starting()
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//配置环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
//banner
Banner printedBanner = printBanner(environment);
//创建context,实例有
//AnnotationConfigApplicationContext
//AnnotationConfigReactiveWebServerApplicationContext
//AnnotationConfigServletWebServerApplicationContext
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 关联context environment listeners
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//启动spring context
refreshContext(context);
//context启动后续操作
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
...省略部分代码
启动入口
核心注解
-
@SpringBootApplication
-
@SpringBootConfiguration
等价@Configuration,@Configuration + @Bean = bean定义(可以理解为xml bean 声明)
-
@EnableAutoConfiguration
spring boot 自动装配,其中AutoConfigurationImportSelector.class为spring boot spi 装载的核心
-
@ComponentScan
spring boot 包扫描 如果不指定默认从声明@ComponentScan 开始扫描
spring boot 自动装配配置类
spring boot 自动状态核心类
AutoConfigurationImportSelector.class
SpringFactoriesLoader.class 从spring.factories 文件中加载 Bean
//加载bean 配置
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//加载配置
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//SpringFactoriesLoader 读spring.facotories 文件
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
自动装配常用的几个注解
-
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class})这个注解的意思是:当存在SqlSessionFactory.class, SqlSessionFactoryBean.class这两个类时才解析MybatisAutoConfiguration配置类,否则不解析这一个配置类,make sence,我们需要mybatis为我们返回会话对象,就必须有会话工厂相关类。
-
@CondtionalOnBean(DataSource.class):只有处理已经被声明为bean的dataSource。
-
@ConditionalOnMissingBean(MapperFactoryBean.class)这个注解的意思是如果容器中不存在name指定的bean则创建bean注入,否则不执行(该类源码较长,篇幅限制不全粘贴)