当前位置 : 主页 > 编程语言 > java >

SpringBoot——Servlet容器启动解析

来源:互联网 收集:自由互联 发布时间:2023-02-04
前言 SpringBoot1.x只区分web环境和非web环境,而在2.x版本中引入了Reactive环境,即响应式环境.那么现在SpringBoot支持三种环境:Servlet的web环境、Reactive的web环境以及非web环境。90%以上的公司使用

前言

SpringBoot1.x只区分web环境和非web环境,而在2.x版本中引入了Reactive环境,即响应式环境.那么现在SpringBoot支持三种环境: Servlet的web环境、Reactive的web环境以及非web环境。90%以上的公司使用的是Servlet的web环境,而该环境默认使用的是tomcat容器,本章内容主要就是介绍Servlet容器启动流程。

Tomcat 是什么

Tomcat 是由 Apache 开发的一个 Servlet 容器,实现了对 Servlet 和 JSP 的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等。

 

由于 Tomcat 本身也内含了一个 HTTP 服务器,它也可以被视作一个单独的 Web 服务器。但是,不能将 Tomcat 和 Apache HTTP 服务器混淆,Apache HTTP 服务器是一个用 C 语言实现的 HTTP Web 服务器;这两个 HTTP web server 不是捆绑在一起的。Tomcat 包含了一个配置管理工具,也可以通过编辑XML格式的配置文件来进行配置。

容器架构

容器处理

启动流程解析

在SpringApplication.run(Application.class,args)里面会构造一个SpringApplication对象,进入其构造函数中

public class SpringApplication { private WebApplicationType webApplicationType; public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); //webApplicationType属性决定了后续容器启动是servlet还是reactive this.webApplicationType = WebApplicationType.deduceFromClasspath(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); } } public enum WebApplicationType { /** * The application should not run as a web application and should not start an * embedded web server. */ NONE, /** * The application should run as a servlet-based web application and should start an * embedded servlet web server. */ SERVLET, /** * The application should run as a reactive web application and should start an * embedded reactive web server. */ REACTIVE; private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext" }; private static final String WEBMVC_INDICATOR_CLASS = "org.springframework." + "web.servlet.DispatcherServlet"; private static final String WEBFLUX_INDICATOR_CLASS = "org." + "springframework.web.reactive.DispatcherHandler"; private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer"; private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext"; private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext"; //通过判断Classpath路径下是否存在某些特定的类,来决定当前是什么样的环境 static WebApplicationType deduceFromClasspath() { if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null) && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) { return WebApplicationType.REACTIVE; } for (String className : SERVLET_INDICATOR_CLASSES) { if (!ClassUtils.isPresent(className, null)) { return WebApplicationType.NONE; } } return WebApplicationType.SERVLET; } }

在SpringApplication的run方法中,context = createApplicationContext()代表创建应用上下文,其就是根据属性webApplicationType来构造什么类

public class SpringApplication { /** * The class name of application context that will be used by default for non-web * environments. */ public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context." + "annotation.AnnotationConfigApplicationContext"; /** * The class name of application context that will be used by default for web * environments. */ public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot." + "web.servlet.context.AnnotationConfigServletWebServerApplicationContext"; /** * The class name of application context that will be used by default for reactive web * environments. */ public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework." + "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext"; public ConfigurableApplicationContext run(String... args) { ...... try { ...... //创建应用上下文 context = createApplicationContext(); ...... } catch (Throwable ex) { ...... } ...... return context; } protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { switch (this.webApplicationType) { case SERVLET: contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); break; case REACTIVE: contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); break; default: contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); } } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass", ex); } } return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); } }

servlet容器启动是在refreshContext(context)方法当中,该方法最终会调用AbstractApplicationContext类中的refresh()方法,该方法会调用onRefresh()方法

private void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } } @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { ...... try { ...... // Initialize other special beans in specific context subclasses. onRefresh(); ...... } catch (BeansException ex) { ...... } finally { ...... } } }

onRefresh()方法由子类实现,根据不同的应用上下文去调用不同的方法,这里为Servlet容器环境,所以调用ServletWebServerApplicationContext类中的onRefresh()方法

public class ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebServerApplicationContext { @Override protected void onRefresh() { super.onRefresh(); try { //构建web服务器 createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start web server", ex); } } private void createWebServer() { // 刚开始这两个属性都为null WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null) { // 走到这步获取WebServerFactory ServletWebServerFactory factory = getWebServerFactory(); //获取WebServerFactory的具体实现之后,调用getWebServer获取一个具体的WebServer, //默认调用TomcatServletWebServerFactory中的getWebServer()方法 this.webServer = factory.getWebServer(getSelfInitializer()); } else if (servletContext != null) { try { getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context", ex); } } initPropertySources(); } protected ServletWebServerFactory getWebServerFactory() { // Use bean names so that we don't consider the hierarchy // 默认返回只有一个,tomcatServletWebServerFactory 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)); } // 获得BeanFactory后调用getBean创建单例bean return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class); } } public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware { // 调用此方法创建webServer @Override public WebServer getWebServer(ServletContextInitializer... initializers) { // 创建一个tomcat Tomcat tomcat = new Tomcat(); // 设置基础目录等属性 File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat"); tomcat.setBaseDir(baseDir.getAbsolutePath()); Connector connector = new Connector(this.protocol); tomcat.getService().addConnector(connector); customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); configureEngine(tomcat.getEngine()); for (Connector additionalConnector : this.additionalTomcatConnectors) { tomcat.getService().addConnector(additionalConnector); } prepareContext(tomcat.getHost(), initializers); return getTomcatWebServer(tomcat); } protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) { // 这步就创建一个TomcatWebServer,里面还会做一些事情...... return new TomcatWebServer(tomcat, getPort() >= 0); } }

接着看initPropertySources()方法

protected void initPropertySources() { ConfigurableEnvironment env = this.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment)env).initPropertySources(this.servletContext, (ServletConfig)null); } } public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) { WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig); } public static void initServletPropertySources(MutablePropertySources sources, @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) { Assert.notNull(sources, "'propertySources' must not be null"); String name = "servletContextInitParams"; // 判断servletContext不为null且包含这个servletContextInitParams属性集 if (servletContext != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) { // 封装一个ServletContextPropertySource属性集替换原有的 sources.replace(name, new ServletContextPropertySource(name, servletContext)); } name = "servletConfigInitParams"; // servletConfig默认为null if (servletConfig != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) { sources.replace(name, new ServletConfigPropertySource(name, servletConfig)); } }

这样就完成了webServer即Tomcat服务器的创建 在进入AbstractApplicationContext中refresh()方法中的finishRefresh()方法中,该方法会根据web容器的环境进行调用,这里会进入ServletWebServerApplicationContext类中的finishRefresh()方法中

@Override protected void finishRefresh() { super.finishRefresh(); //启动WebServer WebServer webServer = startWebServer(); if (webServer != null) { // 发布Server初始完毕事件 publishEvent(new ServletWebServerInitializedEvent(webServer, this)); } } private WebServer startWebServer() { WebServer webServer = this.webServer; if (webServer != null) { webServer.start(); } return webServer; } @Override public void start() throws WebServerException { synchronized (this.monitor) { if (this.started) { return; } try { addPreviouslyRemovedConnectors(); Connector connector = this.tomcat.getConnector(); if (connector != null && this.autoStart) { performDeferredLoadOnStartup(); } checkThatConnectorsHaveStarted(); this.started = true; logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '" + getContextPath() + "'"); } catch (ConnectorStartFailedException ex) { stopSilently(); throw ex; } catch (Exception ex) { throw new WebServerException("Unable to start embedded Tomcat server", ex); } finally { Context context = findContext(); ContextBindings.unbindClassLoader(context, context.getNamingToken(), getClass().getClassLoader()); } } }

启动前准备

webServer创建入口

servlet启动

web容器工厂类加载解析

默认返回只有一个TomcatServletWebServerFactory,那么这个bean定义什么时候被加载到容器中

String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);

它是通过ConfigurationClassParser类中的parse方法,通过@Import注解导入到容器中的

class ConfigurationClassParser { public void parse(Set<BeanDefinitionHolder> configCandidates) { for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { if (bd instanceof AnnotatedBeanDefinition) { parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); } else { parse(bd.getBeanClassName(), holder.getBeanName()); } } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex); } } // 这边会处理@Import注解导入的配置类 this.deferredImportSelectorHandler.process(); } } class ConfigurationClassParser { private class DeferredImportSelectorHandler { public void process() { List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors; this.deferredImportSelectors = null; try { if (deferredImports != null) { DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler(); deferredImports.sort(DEFERRED_IMPORT_COMPARATOR); // 排序并依此遍历调用register方法 deferredImports.forEach(handler::register); handler.processGroupImports(); } } finally { this.deferredImportSelectors = new ArrayList<>(); } } } } class ConfigurationClassParser { private class DeferredImportSelectorGroupingHandler { private final Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>(); private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>(); public void register(DeferredImportSelectorHolder deferredImport) { // 这个返回的Selector就是AutoConfigurationImportSelector,这也是@SpringBootApplication上通过@Import注解 // 导入的Selector. getImportGroup返回的是AutoConfigurationGroup.class Class<? extends Group> group = deferredImport.getImportSelector() .getImportGroup(); // computeIfAbsent就是不存在就创建,这边也是创建一个grouping DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent( (group != null ? group : deferredImport), key -> new DeferredImportSelectorGrouping(createGroup(group))); // this.deferredImports.add(deferredImport); // 加入到了deferredImports中,List<deferredimportselectorholder> deferredImports = new ArrayList&lt;&gt;() grouping.add(deferredImport); // 放入到configurationClasses中 this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getConfigurationClass()); } } }

deferredImports.forEach(handler::register),这边主要是构造了一个grouping,在下一步进行处理handler.processGroupImports()

public void processGroupImports() { for (DeferredImportSelectorGrouping grouping : this.groupings.values()) { // 下面先分析这个getImports方法 grouping.getImports().forEach(entry -> { ConfigurationClass configurationClass = this.configurationClasses.get( entry.getMetadata()); try { processImports(configurationClass, asSourceClass(configurationClass), asSourceClasses(entry.getImportClassName()), false); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to process import candidates for configuration class [" + configurationClass.getMetadata().getClassName() + "]", ex); } }); } } public Iterable<Group.Entry> getImports() { // 这边的deferredImports是通过grouping.add(deferredImport)添加进去的 for (DeferredImportSelectorHolder deferredImport : this.deferredImports) { this.group.process(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getImportSelector()); } return this.group.selectImports(); } // 两个参数如下图所示,annotationMetadata是主配置类上面的注解 @Override public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) { Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector, () -> String.format("Only %s implementations are supported, got %s", AutoConfigurationImportSelector.class.getSimpleName(), deferredImportSelector.getClass().getName())); // 下面先分析下这个getAutoConfigurationEntry方法 AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector) .getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata); this.autoConfigurationEntries.add(autoConfigurationEntry); for (String importClassName : autoConfigurationEntry.getConfigurations()) { // 接着依次遍历放入到这个map中,Map<string, annotationmetadata> entries = new LinkedHashMap() this.entries.putIfAbsent(importClassName, annotationMetadata); } }

这边就到了AutoConfigurationImportSelector类的getAutoConfigurationEntry方法中

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { // 判断是否支持自动配置 if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } // 这个attributes属性就是上图中显示的,用来过滤自动配置类的 AnnotationAttributes attributes = getAttributes(annotationMetadata); // 下面分析这个方法,这个就是加载容器中的自动配置类 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); // 去除重复的,方法就是放入set再放入list中 configurations = removeDuplicates(configurations); // 去除掉应该被排除的 Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); // 通过filter过滤,下面分析,过滤完发现只有22个了 configurations = filter(configurations, autoConfigurationMetadata); // 发布一个事件,好像没有做啥关键的 fireAutoConfigurationImportEvents(configurations, exclusions); // 将configurations封装成AutoConfigurationEntry返回 return new AutoConfigurationEntry(configurations, exclusions); } protected boolean isEnabled(AnnotationMetadata metadata) { if (getClass() == AutoConfigurationImportSelector.class) { // 判断有没有配置这个属性,没有的话默认为true, // String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true); } return true; }

通过filter方法过滤,过滤完发现只有22个了

private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) { long startTime = System.nanoTime(); String[] candidates = StringUtils.toStringArray(configurations); boolean[] skip = new boolean[candidates.length]; boolean skipped = false; for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) { invokeAwareMethods(filter); boolean[] match = filter.match(candidates, autoConfigurationMetadata); for (int i = 0; i < match.length; i++) { if (!match[i]) { skip[i] = true; candidates[i] = null; skipped = true; } } } if (!skipped) { return configurations; } List<String> result = new ArrayList<>(candidates.length); for (int i = 0; i < candidates.length; i++) { if (!skip[i]) { result.add(candidates[i]); } } if (logger.isTraceEnabled()) { int numberFiltered = configurations.size() - result.size(); logger.trace("Filtered " + numberFiltered + " auto configuration class in " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms"); } return new ArrayList<>(result); } protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() { // 看一下这个过滤的逻辑,看下图它的实现类大概就知道它是怎样过滤了 return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader); }

过滤完之后会发现此时List<String> configurations集合中有29个,其中有一个org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration

@Configuration @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @ConditionalOnClass(ServletRequest.class) @ConditionalOnWebApplication(type = Type.SERVLET) @EnableConfigurationProperties(ServerProperties.class) @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, // 会Import一个这个 ServletWebServerFactoryConfiguration.EmbeddedTomcat.class, ServletWebServerFactoryConfiguration.EmbeddedJetty.class, ServletWebServerFactoryConfiguration.EmbeddedUndertow.class }) public class ServletWebServerFactoryAutoConfiguration { ...... } @Configuration class ServletWebServerFactoryConfiguration { @Configuration @ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class }) @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT) public static class EmbeddedTomcat { @Bean public TomcatServletWebServerFactory tomcatServletWebServerFactory() { // 这边就会创建一个TomcatServletWebServerFactory return new TomcatServletWebServerFactory(); } } }

到此为止grouping.getImports方法分析完了,它是返回之前加载的29个自动配置类

class ConfigurationClassParser { private class DeferredImportSelectorGroupingHandler { public void processGroupImports() { for (DeferredImportSelectorGrouping grouping : this.groupings.values()) { grouping.getImports().forEach(entry -> { // 这边这个configurationClass获取的还是主配置类SpringbootApplication ConfigurationClass configurationClass = this.configurationClasses.get( entry.getMetadata()); try { processImports(configurationClass, asSourceClass(configurationClass), asSourceClasses(entry.getImportClassName()), false); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to process import candidates for configuration class [" + configurationClass.getMetadata().getClassName() + "]", ex); } }); } } } }

web容器个性化配置解析

属性注入

工厂类初始化

BeanPostProcessor方法实现

定制化流程

入口,onRefresh方法中会创建webServer,走到这里

public class ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebServerApplicationContext { protected ServletWebServerFactory getWebServerFactory() { // Use bean names so that we don't consider the hierarchy // 默认返回只有一个,tomcatServletWebServerFactory 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)); } // 调用getBean创建工厂类实例,这边会调用getBean开始创建bean实例对象 return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class); } }

在Bean初始化完成之后会遍历BeanFactory中所有的BeanPostProcessor实现,依次调用BeanPostProcessor接口的postProcessBeforeInitialization方法,在创建Web服务的工厂类的时候也会经历这个步骤,这个方法调用点就在AbstractAutowireCapableBeanFactory类中applyBeanPostProcessorsBeforeInitialization()方法

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { @Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { // 通过断点调试可以发现当中有一个WebServerFactoryCustomizerBeanPostProcessor Object current = processor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; } }

可以看到postProcessBeforeInitialization方法多个实现中有一个WebServerFactoryCustomizerBeanPostProcessor 点击进入WebServerFactoryCustomizerBeanPostProcessor类中的postProcessBeforeInitialization方法

public class WebServerFactoryCustomizerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof WebServerFactory) { postProcessBeforeInitialization((WebServerFactory) bean); } return bean; } private void postProcessBeforeInitialization(WebServerFactory webServerFactory) { // 先看下getCustomizers方法 // 这边lamda表达式的意思就是遍历getCustomizers方法,通过invoke调用每个customizer.cutomize方法定制修改web容器 LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory) .withLogger(WebServerFactoryCustomizerBeanPostProcessor.class) .invoke((customizer) -> customizer.customize(webServerFactory)); } private Collection<WebServerFactoryCustomizer<?>> getCustomizers() { if (this.customizers == null) { // Look up does not include the parent context // 获取容器中的所有WebServerFactoryCustomizer this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans()); this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE); this.customizers = Collections.unmodifiableList(this.customizers); } return this.customizers; } private Collection<WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() { return (Collection) this.beanFactory.getBeansOfType(WebServerFactoryCustomizer.class, false, false).values(); } }

我们在来看下图中第二个定制器,ServletWebServerFactoryCustomizer是怎么注入的呢?

@Configuration @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @ConditionalOnClass(ServletRequest.class) @ConditionalOnWebApplication(type = Type.SERVLET) @EnableConfigurationProperties(ServerProperties.class) @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, ServletWebServerFactoryConfiguration.EmbeddedTomcat.class, ServletWebServerFactoryConfiguration.EmbeddedJetty.class, ServletWebServerFactoryConfiguration.EmbeddedUndertow.class }) public class ServletWebServerFactoryAutoConfiguration { // 通过ServletWebServerFactoryAutoConfiguration的bean方法引入到的, // 并且赋值serverProperties @Bean public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) { return new ServletWebServerFactoryCustomizer(serverProperties); } } //这就是我们在application.properties中修改port,会被赋值到这里,然后定制器就可以取到 @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerProperties { /** * Server HTTP port. */ private Integer port; /** * Network address to which the server should bind. */ private InetAddress address; ...... } // 然后我们再来看invoke((customizer) -> customizer.customize(webServerFactory))这个步骤,这会调用每个定制器的定制方法 // 具体我们看下ServletWebServerFactoryCustomizer的cutomize方法 public class ServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered { private final ServerProperties serverProperties; public ServletWebServerFactoryCustomizer(ServerProperties serverProperties) { this.serverProperties = serverProperties; } @Override public int getOrder() { return 0; } @Override public void customize(ConfigurableServletWebServerFactory factory) { PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); // 这边是lamda表达式,调用factory.setPort进行赋值 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()::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); } }

参考: https://my.oschina.net/liwanghong/blog/3168322

https://www.cnblogs.com/hggen/p/6264475.html

https://www.cnblogs.com/jingmoxukong/p/8258837.html

上一篇:SpringBoot——starter解析
下一篇:没有了
网友评论