Spring boot整合tomcat底层原理解析
发布时间:2023-02-20 09:59:06 所属栏目:Tomcat 来源:互联网
导读:从源码层面理解spring boot的默认web容器,以及他们是如何关联起来的。 源码基于spring boot2.6.6 项目的pom.xml中存在spring-boot-starter-web的时候,在项目启动时候就会自动启动一个Tomcat。 自动配置类ServletWebServerFactoryAutoConfiguration找到系统
} spring boot启动的时候启动tomcat SpringBoot的启动过程中,会调用核心的refresh方法,内部会执行onRefresh()方法,onRefresh()方法是一个模板方法,他会执行会执行子类ServletWebServerApplicationContext的onRefresh()方法。 protected void onRefresh() { // 模板方法,先调用它父类的,一般是空方法 super.onRefresh(); try { // 创建web容器 createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start web server", ex); } } 这个方法会调用createWebServer()方法。 // 最核心的俩行代码 private void createWebServer() { ...... // 获取web容器,多个或者没有的时候报错 ServletWebServerFactory factory = getWebServerFactory(); // 调用这个容器的getWebServer方法,上面的启动tomcat的方法! this.webServer = factory.getWebServer(getSelfInitializer()); ...... } getWebServerFactory控制项目组有且只能有一个web容器! protected ServletWebServerFactory getWebServerFactory() { // Use bean names so that we don't consider the hierarchy // 得到所有类型为ServletWebServerFactory的Bean。TomcatServletWebServerFactory、JettyServletWebServerFactory、UndertowServletWebServerFactory都是他得到子类! String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class); // 不存在,报错 if (beanNames.length == 0) { throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean."); } // 存在不止一个,报错! if (beanNames.length > 1) { throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames)); } // 返回唯一的一个web容器! return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class); } 获取tomcat的配置 自动配置类ServletWebServerFactoryAutoConfiguration上除了import三个web容器,还import了BeanPostProcessorsRegistrar。 BeanPostProcessorsRegistrar实现了ImportBeanDefinitionRegistrar,所以他会在spring启动的时候调用registerBeanDefinitions方法。 registerBeanDefinitions会注册一个Bean:webServerFactoryCustomizerBeanPostProcessor。 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // Bean工厂,一个Aware回调进行赋值 if (this.beanFactory == null) { return; } // 注册webServerFactoryCustomizerBeanPostProcessor这个Bean。 registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor", WebServerFactoryCustomizerBeanPostProcessor.class, WebServerFactoryCustomizerBeanPostProcessor::new); // 注册errorPageRegistrarBeanPostProcessor registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor", ErrorPageRegistrarBeanPostProcessor.class, ErrorPageRegistrarBeanPostProcessor::new); } webServerFactoryCustomizerBeanPostProcessor实现了BeanPostProcessor,所以他会在启动的时候调用postProcessBeforeInitialization方法。 private void postProcessBeforeInitialization(WebServerFactory webServerFactory) { // 找到WebServerFactoryCustomizer的Bean LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory) // 标记日志用的类 .withLogger(WebServerFactoryCustomizerBeanPostProcessor.class) // 调用customize方法,传入webServerFactory .invoke((customizer) -> customizer.customize(webServerFactory)); } postProcessBeforeInitialization中会调用WebServerFactoryCustomizer类customize方法,在系统中的唯一实现:ServletWebServerFactoryCustomizer的customize方法。 customize把配置中的内容设置到ConfigurableServletWebServerFactory对象中。他的实现TomcatServletWebServerFactory在启动的时候就会有值! @Override public void customize(ConfigurableServletWebServerFactory factory) { PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(this.serverProperties::getPort).to(factory::setPort); map.from(this.serverProperties::getAddress).to(factory::setAddress); map.from(this.serverProperties.getServlet()::getContextPath).to(factory::setContextPath); map.from(this.serverProperties.getServlet()::getApplicationDisplayName).to(factory::setDisplayName); map.from(this.serverProperties.getServlet()::isRegisterDefaultServlet).to(factory::setRegisterDefaultServlet); map.from(this.serverProperties.getServlet()::getSession).to(factory::setSession); map.from(this.serverProperties::getSsl).to(factory::setSsl); map.from(this.serverProperties.getServlet()::getJsp).to(factory::setJsp); map.from(this.serverProperties::getCompression).to(factory::setCompression); map.from(this.serverProperties::getHttp2).to(factory::setHttp2); map.from(this.serverProperties::getServerHeader).to(factory::setServerHeader); map.from(this.serverProperties.getServlet()::getContextParameters).to(factory::setInitParameters); map.from(this.serverProperties.getShutdown()).to(factory::setShutdown); for (WebListenerRegistrar registrar : this.webListenerRegistrars) { registrar.register(factory); } if (!CollectionUtils.isEmpty(this.cookieSameSiteSuppliers)) { factory.setCookieSameSiteSuppliers(this.cookieSameSiteSuppliers); } } ServletWebServerFactoryCustomizer这个Bean是哪里的? 在我们自动配置类ServletWebServerFactoryAutoConfiguration中定义。 @Bean public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties, ObjectProvider<WebListenerRegistrar> webListenerRegistrars, ObjectProvider<CookieSameSiteSupplier> cookieSameSiteSuppliers) { (编辑:甘南站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |