0
点赞
收藏
分享

微信扫一扫

SpringBoot自学好几天 中途开始写笔记 SpringBoot Web开发 嵌入式Servlet容器自动配置原理 20190130

芒果六斤半 2022-02-07 阅读 75


2.0之前 EmbeddedServletContainerCustomizerAutoConfiguration

2.0之后

EmbeddedWebServerFactoryCustomizerAutoConfiguration

ServletWebServerFactoryAutoConfiguration

嵌入式Servlet容器自动配置

1)EmbeddedWebServerFactoryCustomizerAutoConfiguration

判断容器中引入的依赖 来导入不容的Servlet容器

主要引入了ServerProperties.class 配置文件类

@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties({ServerProperties.class})//配置文件类
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {

//Tomcat为例
@Configuration
@ConditionalOnClass({Tomcat.class, UpgradeProtocol.class})//判断当前是否引入了Tomcat依赖
public static class TomcatWebServerFactoryCustomizerConfiguration {
public TomcatWebServerFactoryCustomizerConfiguration() {
}

//配置tomcat的主要信息
//包含remoteIpValue、connector(最大/最小可接收线程、最大可接收头部大小等等)、uriEncoding、connectionTimeout、maxConnection等属性
@Bean
public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
}
}

2)ServletWebServerFactoryAutoConfiguration

具体的Servlet容器的配置

@Configuration
@AutoConfigureOrder(-2147483648)
@ConditionalOnClass({ServletRequest.class})
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@EnableConfigurationProperties({ServerProperties.class})
@Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class})
//BeanPostProcessorsRegistrar.class 给容器中导入一些组件
//导入了WebServerFactoryCustomizerBeanPostProcessor.class
//BeanPostProcessor 后置处理器 :bean初始化前后(刚创建完对象,还没属性赋值) 执行初始化工作

public class ServletWebServerFactoryAutoConfiguration {

//主要配置tomcat的servlet的信息,
//包含端口、上下文路径、应用名、Session配置、Servlet携带的初始变量等等
//他是继承WebServerFactoryCustomizer的 也就是上一个博客说的个性化定制配置信息的时候提到的
@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
return new ServletWebServerFactoryCustomizer(serverProperties);
}

// 配置tomcat的额外信息
//redirectContextRoot(是否在请求根上下文时转发,true则转发路径为/demoWeb/)和useRelativeRedirects(是否使用相对路径)等路径跳转问题处理
@Bean
@ConditionalOnClass(
name = {"org.apache.catalina.startup.Tomcat"}
)
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}

TomcatWebServerFactoryCustomizer

ServletWebServerFactoryCustomizer

TomcatServletWebServerFactoryCustomizer

这三个类基本完成了Tomcat的配置,他们都是WebServerFactoryCustomizer的实现类,

那么谁来统一调用以完成上述的配置呢?

  1. 引入了WebServerFactory工厂类,创建了TomcatServletWebServerFactory的tomcat容器
@EnableConfigurationProperties({ServerProperties.class})
@Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class})
public class ServletWebServerFactoryAutoConfiguration {

//上边 EmbeddedTomcat.class
@Configuration
@ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})
@ConditionalOnMissingBean(
value = {ServletWebServerFactory.class},
search = SearchStrategy.CURRENT
)
public static class EmbeddedTomcat {
public EmbeddedTomcat() {
}

@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
  1. 通过beanPostProcessor接口来完成相应的容器初始化,
    注册了webServerFactoryCustomizerBeanPostProcessor类来完成相应的tomcat个性化配置
@EnableConfigurationProperties({ServerProperties.class})
@Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class})
public class ServletWebServerFactoryAutoConfiguration {

//上边ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class
public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
private ConfigurableListableBeanFactory beanFactory;

public BeanPostProcessorsRegistrar() {
}

public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (beanFactory instanceof ConfigurableListableBeanFactory) {
this.beanFactory = (ConfigurableListableBeanFactory)beanFactory;
}

}

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (this.beanFactory != null) {
this.registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor", WebServerFactoryCustomizerBeanPostProcessor.class);
this.registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor", ErrorPageRegistrarBeanPostProcessor.class);
}
}

private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name, Class<?> beanClass) {
if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(name, beanDefinition);
}

}
}

WebServerFactoryCustomizerBeanPostProcessor:

public class WebServerFactoryCustomizerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private ListableBeanFactory beanFactory;
private List<WebServerFactoryCustomizer<?>> customizers;

public WebServerFactoryCustomizerBeanPostProcessor() {
}

public void setBeanFactory(BeanFactory beanFactory) {
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory, "WebServerCustomizerBeanPostProcessor can only be used with a ListableBeanFactory");
this.beanFactory = (ListableBeanFactory)beanFactory;
}
//调用所有实现了WebServerFactoryCustomizer接口的对象 可能会包含自己定制的
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebServerFactory) {
this.postProcessBeforeInitialization((WebServerFactory)bean);
}

return bean;
}
// // 查找当前bean工厂中所有类型为WebServerFactoryCustomizer接口对象集合
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}

private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
((Callbacks)LambdaSafe.callbacks(WebServerFactoryCustomizer.class, this.getCustomizers(), webServerFactory, new Object[0]).withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)).invoke((customizer) -> {
customizer.customize(webServerFactory);
});
}

private Collection<WebServerFactoryCustomizer<?>> getCustomizers() {
if (this.customizers == null) {
this.customizers = new ArrayList(this.getWebServerFactoryCustomizerBeans());
this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}

return this.customizers;
}

private Collection<WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() {
return this.beanFactory.getBeansOfType(WebServerFactoryCustomizer.class, false, false).values();
}
}

步骤:


  1. SpringBoot根据导入依赖情况 ,给容器中添加相应的嵌入式工厂
    SpringBoot自学好几天 中途开始写笔记 SpringBoot Web开发  嵌入式Servlet容器自动配置原理  20190130_嵌入式
  2. ServletWebServerFactoryAutoConfiguration
    ServletWebServerFactoryCustomizer 和 TomcatServletWebServerFactoryCustomizer 配置其他配置
  3. WebServerFactoryCustomizerBeanPostProcessor 后置处理器
    从容器中获取所有的ConfigurableListableBeanFactory

有有有有有点儿乱 就是简单了解以下

嵌入式Servlet容器启动原理

什么时候创建嵌入式的Servlet容器工厂 什么时候获取嵌入式的Servlet容器并启动Tomcat


  1. SpringBoot应用启动运行run方法
  2. refreshContext 刷新IOC容器【创建IOC容器对象 并初始化容器 创建容器中每一个组件】
  3. refresh刷新刚才创建的IOC容器
  4. onRefresh();web的ioc容器 重写了onRefresh方法
  5. WEB IOC容器创建嵌入式Servlet容器 createEmbededServletContainer
    6.获取嵌入式Servlet容器工厂 这个工厂就是上边自动注入放进去的
  6. Servlet容器工厂创建了 就会配置相关配置 然后会触发后置处理器 ,后置处理器会获取所有定制器 定制Servlet相关配置
  7. 容器工厂获取完 用容器工厂获取嵌入式的Servlet容器
  8. 嵌入式Servlet容器创建Tocmat对象 并启动
    先启动嵌入式Servlet容器 再将IOC容器中剩下没有创建的对象获取出来


举报

相关推荐

0 条评论