Java-第十五部分-源码解读-SpringBoot-Run和配置过程

156 阅读2分钟

源码解读全文

SpringBoot

  • 整合了SpringSpringMVC
  • 依赖环节,抽取了各种starter,自动导入了很多组件
  • 底层容器为ServletWebServerApplicationContext

Run方法

  • 创建IOC容器 context = createApplicationContext();,加载配置
  • 刷新IOC容器refreshContext(context);,进行容器刷新12大步
  • 其中实际的容器类ServletWebServerApplicationContext,重写了onRefresh,创建了Tomcat服务器
  • Tomcat启动,通过ServlertContextInitializeronStartup回调,注册所有Servlet
  • DispatcherServlet初始化机制,创建父子容器,加载九大组件

@SpringBootApplication

  • 给容器中加载组件
  • @SpringBootConfiguration为配置类,会被后置处理器分析
  • @EnableAutoConfiguration,导入组件
  1. @AutoConfigurationPackage,自动配置包,导入组件@Import(AutoConfigurationPackages.Registrar.class)
  2. @Import(AutoConfigurationImportSelector.class)

AutoConfigurationPackages.Registrar

  • 最终调用registry.registerBeanDefinition(BEAN, new BasePackagesBeanDefinition(packageNames));
  1. String BEAN = AutoConfigurationPackages.class.getName();
  2. packageNames = com.java.boot
  • 导入扫描包的定义信息,指定要扫描哪些包 image.png
  • 当处理到这个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,进行懒加载并进行缓存 image.png
  • 利用SPI机制,加载"META-INF/spring.factories";中的EnableAutoConfiguration对应的所有配置的类 image.png image.png

SpringBoot中的DispatcherServlet

  • SpringBoot准备了一个DispatcherServlet放入嵌入式Tomcat
  • DispatcherServletAutoConfiguration进行DispatcherServlet的配置,需要先配置ServletWebServerFactoryAutoConfiguration,处理ServletWeb服务器的配置 image.png

ServletWebServerFactoryAutoConfiguration

  • ServerProperties.class加载server开头的配置 image.png
  • 导入BeanPostProcessorsRegistrar.class

注册WebServerFactoryCustomizerBeanPostProcessor后置增强

  • 导入三种不同的服务器,根据条件@ConditionalOnClass,决定使用哪个服务器
  1. EmbeddedTomcat
  2. EmbeddedJetty
  3. EmbeddedUndertow image.png

EmbeddedTomcat

  • 注入了TomcatServletWebServerFactory,作为ServletWebServerFactory服务器工厂,产生并启动服务器
  • 构造参数从容器中获取 image.png
  • TomcatServletWebServerFactory中包含getWebServer创建Tomcat image.png

过程

  • run方法
  • applicationContext.refresh();

容器为AnnotationConfigServletWebServerApplicationContext,为ServletWebServerApplicationContext的子类

  • 调用superrefresh(),为AbstractApplicationContext容器刷新十二大步,进行onfresh(),由子类重写,调用createWebServer();,创建Web服务器
  • 通过getBean获取ServletWebServerFactoryServletWebServerFactory factory = getWebServerFactory();,最终加载TomcatServletWebServerFactory,加载Tomcat服务器工厂
  1. 其中configureContext(context, initializersToUse);initializersToUseServlertContextInitializer
  2. 说明Tomcat启动时,需要ServlertContextInitializer
  • 创建服务器,进行服务器配置this.webServer = factory.getWebServer(getSelfInitializer());,调用getTomcatWebServer(tomcat);,最终this.tomcat.start();启动

DispatcherServletAutoConfiguration

  • DispatcherServletRegistrationBean通过ServlertContextInitializeronStartup,在Tomcat启动完成后,将自己注册

DispatcherServletRegistrationBean

  • DispatcherServletRegistrationBean,实现了ServlertContextInitializer image.png
  • 在创建Bean时,需要DispatcherServlet image.png
  • 即当TomcatServer启动时,getWebServerFactory();prepareContext(tomcat.getHost(), initializers); 准备上下文

其中ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);,获取所有initializer,其中包括DispatcherServletRegistrationBean

  • 处理上下文configureContext(context, initializersToUse);,创建TomcatStarter starter = new TomcatStarter(initializers);
  • TomcatStarterstart后,调用onStartup时,其中遍历所有的initializerinitializer.onStartup(servletContext);
  • 调用RegistrationBeanonStartupregister(description, servletContext);,注册进Tomcat中,其中也包括DispatcherServlet

DispatcherServletRegistrationBean继承了RegistrationBean image.png

  • 最终调用ServletRegistrationBeanconfigure,将映射信息注册registration.addMapping(urlMapping);