SpringBoot嵌入式Servlet容器自动配置原理

本文介绍SpringBoot嵌入式Servlet容器自动配置原理,涉及嵌入式Servlet容器自动配置类、工厂类。以Tomcat为例,若导入相关依赖且未自定义容器,SpringBoot会自动注入工厂。还说明了对嵌入式容器配置修改的生效方式,总结了配置的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringBoot嵌入式Servlet容器自动配置原理

EmbeddedServletContainerAutoConfiguration:嵌入式的Servlet容器自动配置类

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication // Web应用下自动配置才会生效
@Import(BeanPostProcessorsRegistrar.class) // 导入BeanPostProcessorsRegistrar
// 导入了EmbeddedServletContainerCustomizerBeanPostProcessor:
// BeanPostProcessor:后置处理器:bean初始化前后(创建完对象,还没属性赋值)执行初始化工作
public class EmbeddedServletContainerAutoConfiguration {

	@Configuration
	@ConditionalOnClass({ Servlet.class, Tomcat.class }) // 容器中引入了Tomcat依赖配置才会生效
	@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT) // 容器中没有用户自定义的EmbeddedServletContainerFactory(嵌入式Servlet容器工厂)才会生效
	public static class EmbeddedTomcat {

		@Bean
		public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory(){
			return new TomcatEmbeddedServletContainerFactory();
		}

	}
  
  // 下面Jetty和Undertow同理,根据容器中导入的依赖,来导入不同的Servlet容器工厂
	@Configuration
	@ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
			WebAppContext.class })
	@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
	public static class EmbeddedJetty {

		@Bean
		public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
			return new JettyEmbeddedServletContainerFactory();
		}

	}

	@Configuration
	@ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
	@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
	public static class EmbeddedUndertow {

		@Bean
		public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory({
			return new UndertowEmbeddedServletContainerFactory();
		}

	}
}
  • EmbeddedServletContainerAutoConfiguration:嵌入式Servlet容器工厂类
package org.springframework.boot.context.embedded;

import org.springframework.boot.web.servlet.ServletContextInitializer;

// 获取嵌入式的Servlet容器
public interface EmbeddedServletContainerFactory {
    EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... var1);
}

[外链图片转存失败(img-iPX5j1kp-1563123406747)(/Users/guih/Desktop/WX20190714-225718.png)]

从类关系图中可以看到有三种Servlet容器工厂

  • EmbeddedServletContainer:嵌入式Servlet容器

[外链图片转存失败(img-dMkKQ2og-1563123406748)(/Users/guih/Desktop/WX20190714-225915.png)]

对应的Servlet容器也是三种

以Tomcat为例分析:如果导入了Tomcat依赖,并且没有自定义Servlet内置容器,SpringBoot则会自动注入一个TomcatEmbeddedServletContainerFactory(在上面的代码中可以看出)

// AbstractEmbeddedServletContainerFactory类部分代码

	@Override
	public EmbeddedServletContainer getEmbeddedServletContainer(
			ServletContextInitializer... initializers) {
    // 创建Tomcat
		Tomcat tomcat = new Tomcat();
    
    // 配置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);
    
    // 传入配置好的Tomcat,返回一个嵌入式Servlet容器,并启动Tomcat服务器
		return getTomcatEmbeddedServletContainer(tomcat);
	}

对嵌入式容器的配置修改是如何生效

EmbeddedServletContainerCustomizer:定制器帮我们修改了Servlet容器的配置?

容器中导入了BeanPostProcessorsRegistrar(类中的注解@Import),在这中间又导入了EmbeddedServletContainerCustomizerBeanPostProcessor

	// EmbeddedServletContainerCustomizerBeanPostProcessor部分代码

	// 初始化之前
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
    // 如果当前初始化的是一个ConfigurableEmbeddedServletContainer类型的组件
		if (bean instanceof ConfigurableEmbeddedServletContainer) {
			postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
		}
		return bean;
	}


  private void postProcessBeforeInitialization(
        ConfigurableEmbeddedServletContainer bean) {
      // 获取所有的定制器,调用每一个定制器的customize方法来给Servlet容器进行属性赋值;
      for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
          customizer.customize(bean);
      }
  }

  private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
      if (this.customizers == null) {
          // Look up does not include the parent context
          this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(
              this.beanFactory
              //从容器中获取所有这个类型的组件:EmbeddedServletContainerCustomizer
              //定制Servlet容器,给容器中可以添加一个EmbeddedServletContainerCustomizer类型的组件
              .getBeansOfType(EmbeddedServletContainerCustomizer.class,
                              false, false)
              .values());
          Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
          this.customizers = Collections.unmodifiableList(this.customizers);
      }
      return this.customizers;
  }
	

步骤总结:

1)、SpringBoot根据导入的依赖情况,给容器中添加相应的EmbeddedServletContainerFactory【TomcatEmbeddedServletContainerFactory】

2)、容器中某个组件要创建对象就会惊动后置处理器;EmbeddedServletContainerCustomizerBeanPostProcessor;只要是嵌入式的Servlet容器工厂,后置处理器就工作;

3)、后置处理器,从容器中获取所有的EmbeddedServletContainerCustomizer,调用定制器的定制方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值