SpringBoot内置Servlet源码解析:容器自动配置( 二 )
EmbeddedTomcat 自动配置的条件是类路径中存在 Servlet、Tomcat、UpgradeProtocol这 3 个类 , 并且 ServletWebServerFactory 不存在 。
在上述代码中 , 需要注意@ConditionalOnMissingBean 注解的 search 属性 。 search 属 性支持的搜索策略类型定义在枚举类 SearchStrategy 中 , 包括 CURRENT、ANCESTORS、ALL 。 这 3 种策略类型依次对应的作用范围为:搜索当前容器、搜索所有祖先容器(不包括当前容器)、搜索所有层级容器 。
默认情况下 , search 属性的值为 ALL , 也就是搜索所有层级容器 , 而此处 Search 属性是CURRENT,即搜索范围是当前容器 。
TomcatServletWebServerFactory 的实例化方法 tomcatServletWebServerFactory 是由 3个 ObjectProvider 参数构成 。
ObjectProvider 参 数 中 的 泛 型 依 次 包 括 TomcatConnector-Customizer 、
TomcatContextCustomizer 和 TomcatProtocolHandlerCustomizer>,它们均为回调接口 。
TomcatConnectorCustomizer 用于 Tomcat Connector 的定制化处理 ,
TomcatContextCustomizer 用于 Tomcat Context 的定制化处理 ,
TomcatProtocolHandlerCustomizer>用于 TomcatConnector 中 ProtocolHandler 的定制化处理 。 也就是说 , 通过以上回调函数 , 可以在核心业务处理完成之后 , 针对 Tomcat 再进行一些定制化操作 。
关于 ObjectProvider 的使用 , 我们在此稍微拓展一-下 , 有助于我们加深理解 。 Object-Provider 接口从 Spring 4.3 版本开始引入 , 它是 ObjectFactory 的一种变体 , 是专门为注入设计的 。 在正常情况下 , 如果构造方法依赖某个 Bean,则需通过@Autowired 进行注入 ,并且在单构造函数时可以默认省略掉@Autowired 隐式注入 。
但如果待注入的参数的 Bean 为空或有多个时 , 便是 ObjectProvider 发挥作用的时候了 。 如果注入实例为空 , 使用 ObjectProvider 则避免了强依赖导致的依赖对象不存在;如果有多个实例 , ObjectProvider 的方法会 根据 Bean 实现的 Ordered 接口或@Order 注解指定的先后顺序获取一个 Bean,从而提供一个更加宽松的依赖注入方式 。 Spring 5.1 版本之后提供了基于 Stream 的 orderedStream 方法来获取有序的 Stream,这也正是上面源代码中所使用的方法 。
TomcatServletWebServerFactory 的实例化代码非常简单 , 只是调用了无参的构造方法 。 该工厂方法的层级比较复杂 , 我们也没必要详细说明所有的父类或接口 , 只需要知道该类最终是 WebServerFactory 接口的实现即可 。
这里先顺便了解一下 TomcatServletWebServerFactory 中两个常见的 Web 应用的默认值:contextPath 和 port, 即我们通常讲的访问路径和端口 。 在调用无参构造方法时 , 这两个参数分别默认定义在 AbstractServletWebServerFactory 和AbstractConfigurableWebServerFactory 类中 。
TomcatServletWebServerFactory 的 父 类 AbstractServletWebServerFactory 中 定 义 了context-Path 的默认值 , 代码如下 。
public abstract class AbstractServletWebServerFactory extends AbstractConfigura -bleWebServerFactory implements ConfigurableServletWebServerFactory {private String contextPath = "";}AbstractServletWebServerFactory 的父类 AbstractConfigurableWebServerFactory 中定义了 port 的默认值 , 代码如下 。 public abstract class AbstractConfigurableWebServerFactory implements Configura-bleWebServerFactory {private int port = 8080 ; 。。。 }当然 , 还有其他许多默认值 , 比如编码(UTF-8) 等 , 内容过于细碎 , 读者可自行查阅相关源代码进行了解在 ServletWebServerFactoryConfiguration 类中还提供了自动配置JettyServletWebServerFactory 和 UndertowServletWebServerFactory 的 内 部 类,与Tomcat 的操作基本一致 , 不再重复讲解 。
现在我们回归最初的主线继续看 ServletWebServerFactoryAutoConfiguration 引入的另外一个类:ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar 。 很显然 , 它是当前自动配置类的内部类 , 源代码如下 。
//通过实现 ImportBeanDefinitionRegistrar 来注册一 ^WebServerFac toryCus tomizerBean-PostProcessorpublic static class BeanPostProces sorsRegistrar implements ImportBeanDefinitionRe-gistrar, BeanF actoryAwareprivate ConfigurablelistableBeanFactory beanF actory;//实现 BeanFactoryAware 的方法 , 设 置 BeanFactory@Overridepublic void setBeanFactory(BeanF actory beanFactory) throws BeansException {if (beanFactory instanceof Conf igurableListableBeanFactory) {this . beanFactory = (ConfigurableListableBeanFactory) beanFactory;//注册一^WebServerFac toryCus tomizerBeanPostProcessor@Overridepublic void registerBeanDefinitions (Annotat ionMetadata importingClassMetadata,BeanDefinitionRegistry registry) {if (this. beanFactory == null) {return;}registerSyntheticBeanIfMissing(registry, " 'webServerFactoryCustomizer-BeanPostProcessor",WebServerFactoryCustomizerBeanPostProcessor .class);registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPost -Processor",ErrorPageRegistrarBeanPostProcessor . class);//检查卉注册 Beanprivate void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, Stringname, Class
- SpringBoot+MyBatis+MySQL读写分离实现
- SpringBoot构造流程源码分析:Web应用类型推断
- 搭建私有Sentry日志收集系统并集成到springboot
- 待机一周内置小爱同学,还能查看跳绳数据,开箱小寻学习手表S5
- 欧洲航天局3D打印世界上第一个内置电子模块的数据传输设备
- 创新6叶刀片设计,内置电控智能算法,须眉小钢鲨震撼来袭
- SpringBoot扫描不到组件?给你提供几种方案
- 价格战|小米重打价格战?新款智能手表:内置小爱+NFC,仅269元
- 内置|续航时间最长的5部5G手机:小米拿到第一,网友:大电池就是好
- SpringBoot自定义错误页面
