springboot启动流程
1.创建springApplication对象
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer,然后保存起来
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//从类路径下找到META-INF/spring.factories配置的所有 ApplicationListener,然后保存起来
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//推断主配置类
this.mainApplicationClass = deduceMainApplicationClass();
}
2.运行run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//从类路径下找到META-INF/spring.factories配置的所有SpringApplicationRunListeners
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
//封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
//打印banner
Banner printedBanner = printBanner(environment);
//创建IOC容器,决定创建的是web的IOC还是普通的IOC
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//准备上下文,回调所有的ApplicationContextInitializer的initialize方法,所有的SpringApplicationRunListener的contextPrepared方法
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//刷新容器,IOC容器初始化,所有的单实例bean初始化,如果是web应用,还会创建嵌入式的Tomcat
//扫描,创建,加载所有的组件
refreshContext(context);
//从IOC容器中获取所有的ApplicationRunner和CommandLineRunner,分别进行回调
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;
}
springboot启动事件
几个重要的事件回调机制
ApplicationContextInitializer 配置在META-INF/spring.factories中
SpringApplicationRunListener 配置在META-INF/spring.factories中
ApplicationRunner 放在IOC容器中
CommandLineRunner 放在IOC容器中
springboot自动配置原理
1.springboot在启动时加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
2.@EnableAutoConfiguration 作用:
利用EnableAutoConfigurationImportSelector给容器导入一些组件
可以查看selectImports()方法的内容
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
SpringFactoriesLoader.loadFactoryNames()
扫描所有jar包类路径下 META-INF/spring.factories中的内容
把扫描到的这些文件的内容包装成properties对象
从properties中获取到EnabAutoConfiguration.class对应的值,然后把它们添加到容器中

每一个XXXAutoConfiguration都是容器的一个组件,都加入到容器中,用它们来做自动配置
3.每一个自动配置类进行自动配置功能
4.以 HttpEncodingAutoConfiguration 为例解释自动配置功能
@Configuration(proxyBeanMethods = false) //表示这是一个配置类
@EnableConfigurationProperties(HttpProperties.class) //启动指定类的ConfigurationProperties功能
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) //根据不同的条件,如果满足指定的条件,整个配置类才会生效
@ConditionalOnClass(CharacterEncodingFilter.class) //判断当前项目中有没有CharacterEncodingFilter,如果有,才会生效
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)//判断配置文件中是否存在某个配置 spring.http.encoding.enabled,matchIfMissing = true表示即使没有配置,也可以生效
public class HttpEncodingAutoConfiguration
根据当前不同的条件判断,决定这个配置类是否生效,一旦生效,使用@Bean给容器中添加一个组件
@Bean //给容器中添加一个组件
@ConditionalOnMissingBean //在不存在该Bean的情况下添加
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
return filter;
}
5.所有在配置文件中能配置的属性都是在XXProperties中封装着,配置文件能配置什么就可以参考这个类中的属性
@ConfigurationProperties(prefix = "spring.http")
public class HttpProperties