经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Servlet » 查看文章
Spring Boot 中嵌入式 Servlet 容器自动配置原理解析
来源:jb51  时间:2021/11/9 12:48:35  对本文有异议

1.参照 Spring Boot 自动配置包里面的web模块

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

  1. @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
  2. @Configuration
  3. @ConditionalOnWebApplication
  4. @Import(BeanPostProcessorsRegistrar.class)
  5. //导入BeanPostProcessorsRegistrar:Spring注解版;给容器中导入一些组件
  6. //导入了EmbeddedServletContainerCustomizerBeanPostProcessor:
  7. //后置处理器:bean初始化前后(创建完对象,还没赋值赋值)执行初始化工作
  8. public class EmbeddedServletContainerAutoConfiguration {
  9. .....
  10. @Configuration
  11. @ConditionalOnClass({ Servlet.class, Tomcat.class })//判断当前是否引入了Tomcat依赖;
  12. @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)//判断当前容器没有用户自己定义EmbeddedServletContainerFactory:嵌入式的Servlet容器工厂;作用:创建嵌入式的Servlet容器
  13. public static class EmbeddedTomcat {
  14. @Bean
  15. public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
  16. return new TomcatEmbeddedServletContainerFactory();
  17. }
  18. }
  19. /**
  20. * Nested configuration if Jetty is being used.
  21. */
  22. @Configuration
  23. @ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
  24. WebAppContext.class })
  25. @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
  26. public static class EmbeddedJetty {
  27. @Bean
  28. public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
  29. return new JettyEmbeddedServletContainerFactory();
  30. }
  31. }
  32. /**
  33. * Nested configuration if Undertow is being used.
  34. */
  35. @Configuration
  36. @ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
  37. @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
  38. public static class EmbeddedUndertow {
  39. @Bean
  40. public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
  41. return new UndertowEmbeddedServletContainerFactory();
  42. }
  43. }

2.EmbeddedServletContainerFactory(嵌入式Servlet容器工厂)

  1. public interface EmbeddedServletContainerFactory {
  2. //获取嵌入式的Servlet容器
  3. EmbeddedServletContainer getEmbeddedServletContainer(
  4. ServletContextInitializer... initializers);
  5. }

Ctrl+H 显示继承关系:

3.EmbeddedServletContainer(嵌入式的Servlet容器)

4.以TomcatEmbeddedServletContainerFactory为例

  1. @Override
  2. public EmbeddedServletContainer getEmbeddedServletContainer(
  3. ServletContextInitializer... initializers) {
  4. //创建一个Tomcat
  5. Tomcat tomcat = new Tomcat();
  6. //配置Tomcat的基本环节
  7. File baseDir = (this.baseDirectory != null ? this.baseDirectory
  8. : createTempDir("tomcat"));
  9. tomcat.setBaseDir(baseDir.getAbsolutePath());
  10. Connector connector = new Connector(this.protocol);
  11. tomcat.getService().addConnector(connector);
  12. customizeConnector(connector);
  13. tomcat.setConnector(connector);
  14. tomcat.getHost().setAutoDeploy(false);
  15. configureEngine(tomcat.getEngine());
  16. for (Connector additionalConnector : this.additionalTomcatConnectors) {
  17. tomcat.getService().addConnector(additionalConnector);
  18. }
  19. prepareContext(tomcat.getHost(), initializers);
  20. //将配置好的Tomcat传入进去,返回一个EmbeddedServletContainer;并且启动Tomcat服务器
  21. return getTomcatEmbeddedServletContainer(tomcat);
  22. }

5.嵌入式容器的配置修改生效原理

依次向下生效:

  • ServerProperties:绑定配置文件里面的属性
  • EmbeddedServletContainerCustomizer:嵌入式Servlet容器的定制器,修改Servlet容器配置
  • EmbeddedServletContainerCustomizerBeanPostProcessor
  1. //初始化之前
  2. @Override
  3. public Object postProcessBeforeInitialization(Object bean, String beanName)
  4. throws BeansException {
  5. //如果当前初始化的是一个ConfigurableEmbeddedServletContainer类型的组件
  6. if (bean instanceof ConfigurableEmbeddedServletContainer) {
  7. //
  8. postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
  9. }
  10. return bean;
  11. }
  12. private void postProcessBeforeInitialization(
  13. ConfigurableEmbeddedServletContainer bean) {
  14. //获取所有的定制器,调用每一个定制器的customize方法来给Servlet容器进行属性赋值;
  15. for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
  16. customizer.customize(bean);
  17. }
  18. }
  19. private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
  20. if (this.customizers == null) {
  21. // Look up does not include the parent context
  22. this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(
  23. this.beanFactory
  24. //从容器中获取所有这葛类型的组件:EmbeddedServletContainerCustomizer
  25. //定制Servlet容器,给容器中可以添加一个EmbeddedServletContainerCustomizer类型的组件
  26. .getBeansOfType(EmbeddedServletContainerCustomizer.class,
  27. false, false)
  28. .values());
  29. Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
  30. this.customizers = Collections.unmodifiableList(this.customizers);
  31. }
  32. return this.customizers;
  33. }
  34. //ServerProperties也是定制器

步骤:

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

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

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

本文需结合代码片段内的文字注释浏览。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号