源码解读全文
SpringBoot
- 整合了
Spring和SpringMVC - 依赖环节,抽取了各种
starter,自动导入了很多组件 - 底层容器为
ServletWebServerApplicationContext
Run方法
- 创建IOC容器
context = createApplicationContext();,加载配置 - 刷新IOC容器
refreshContext(context);,进行容器刷新12大步 - 其中实际的容器类
ServletWebServerApplicationContext,重写了onRefresh,创建了Tomcat服务器 Tomcat启动,通过ServlertContextInitializer的onStartup回调,注册所有ServletDispatcherServlet初始化机制,创建父子容器,加载九大组件
@SpringBootApplication
- 给容器中加载组件
@SpringBootConfiguration为配置类,会被后置处理器分析@EnableAutoConfiguration,导入组件
@AutoConfigurationPackage,自动配置包,导入组件@Import(AutoConfigurationPackages.Registrar.class)@Import(AutoConfigurationImportSelector.class)
AutoConfigurationPackages.Registrar
- 最终调用
registry.registerBeanDefinition(BEAN, new BasePackagesBeanDefinition(packageNames));
String BEAN = AutoConfigurationPackages.class.getName();packageNames = com.java.boot
- 导入扫描包的定义信息,指定要扫描哪些包
- 当处理到这个
BeanDefinition时,会进行包扫描
AutoConfigurationImportSelector
ConfigurationClassPostProcessor处理过程中,被扫描到进行注解解析并最终调用getAutoConfigurationEntry
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取所有的`EnableAutoConfiguration`的属性类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//去重
configurations = removeDuplicates(configurations);
//排除
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//过滤掉不能使用的类,依赖类
configurations = getConfigurationClassFilter().filter(configurations);
//发送事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
- 其中最终调用
loadSpringFactories,进行懒加载并进行缓存 - 利用SPI机制,加载
"META-INF/spring.factories";中的EnableAutoConfiguration对应的所有配置的类
SpringBoot中的DispatcherServlet
SpringBoot准备了一个DispatcherServlet放入嵌入式Tomcat中DispatcherServletAutoConfiguration进行DispatcherServlet的配置,需要先配置ServletWebServerFactoryAutoConfiguration,处理ServletWeb服务器的配置
ServletWebServerFactoryAutoConfiguration
ServerProperties.class加载server开头的配置- 导入
BeanPostProcessorsRegistrar.class
注册
WebServerFactoryCustomizerBeanPostProcessor后置增强
- 导入三种不同的服务器,根据条件
@ConditionalOnClass,决定使用哪个服务器
EmbeddedTomcatEmbeddedJettyEmbeddedUndertow
EmbeddedTomcat
- 注入了
TomcatServletWebServerFactory,作为ServletWebServerFactory服务器工厂,产生并启动服务器 - 构造参数从容器中获取
TomcatServletWebServerFactory中包含getWebServer创建Tomcat
过程
run方法applicationContext.refresh();
容器为
AnnotationConfigServletWebServerApplicationContext,为ServletWebServerApplicationContext的子类
- 调用
super的refresh(),为AbstractApplicationContext容器刷新十二大步,进行onfresh(),由子类重写,调用createWebServer();,创建Web服务器 - 通过
getBean获取ServletWebServerFactory,ServletWebServerFactory factory = getWebServerFactory();,最终加载TomcatServletWebServerFactory,加载Tomcat服务器工厂
- 其中
configureContext(context, initializersToUse);,initializersToUse为ServlertContextInitializer- 说明
Tomcat启动时,需要ServlertContextInitializer
- 创建服务器,进行服务器配置
this.webServer = factory.getWebServer(getSelfInitializer());,调用getTomcatWebServer(tomcat);,最终this.tomcat.start();启动
DispatcherServletAutoConfiguration
DispatcherServletRegistrationBean通过ServlertContextInitializer的onStartup,在Tomcat启动完成后,将自己注册
DispatcherServletRegistrationBean
DispatcherServletRegistrationBean,实现了ServlertContextInitializer- 在创建
Bean时,需要DispatcherServlet - 即当
TomcatServer启动时,getWebServerFactory();,prepareContext(tomcat.getHost(), initializers);准备上下文
其中
ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);,获取所有initializer,其中包括DispatcherServletRegistrationBean
- 处理上下文
configureContext(context, initializersToUse);,创建TomcatStarter starter = new TomcatStarter(initializers); TomcatStarter中start后,调用onStartup时,其中遍历所有的initializer,initializer.onStartup(servletContext);- 调用
RegistrationBean的onStartup,register(description, servletContext);,注册进Tomcat中,其中也包括DispatcherServlet
DispatcherServletRegistrationBean继承了RegistrationBean
- 最终调用
ServletRegistrationBean的configure,将映射信息注册registration.addMapping(urlMapping);