zoukankan      html  css  js  c++  java
  • springboot(八) 嵌入式Servlet容器自动配置原理和容器启动原理

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

    1.1 在spring-boot-autoconfigure-1.5.9.RELEASE.jar => springboot自动配置依赖 jar包下,EmbeddedServletContainerAutoConfiguration => 嵌入式servlet容器自动配置类

    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @Configuration
    @ConditionalOnWebApplication  //如果是web应用,当前配置类生效
    @Import(BeanPostProcessorsRegistrar.class) //Bean后置处理器的注册器;给容器中注入一些组件
    //导入了EmbeddedServletContainerCustomizerBeanPostProcessor
    //后置处理器功能:在bean初始化前后(刚创建完对象,还没属性赋值)执行初始化工作
    public class EmbeddedServletContainerAutoConfiguration { /** * Nested configuration if Tomcat is being used. */ @Configuration @ConditionalOnClass({ Servlet.class, Tomcat.class }) //判断当前是否引入了Tomcat依赖; @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT) //判断当前容器没有
    用户自定义的EmbeddedServletContainerFactory(嵌入式servlet容器工厂);作用:创建servlet容器;
        
    public static class EmbeddedTomcat { @Bean public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() { return new TomcatEmbeddedServletContainerFactory(); } }

    1.2 EmbeddedServletContainerFactory(嵌入式servlet容器工厂)

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

    1.3 EmbeddedServletContainer(嵌入式servlet容器)

     1.4 以TomcatEmbeddedServletContainerFactory为例

        @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传入进去。返回一个EmbeddedServletContainer 并且启动tomcat容器
    return getTomcatEmbeddedServletContainer(tomcat); }

    1.4.1 我们对server的修改是怎么生效的呢?

    ServerPorperties ,EmbeddedServletContainerCustomizer

    EmbeddedServletContainerCustomizer帮我们修改了server配置,修改的原理是:

    容器中也导入了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;
    }

    2.嵌入式Servlet容器启动原理

     2.1 获取嵌入式servlet容器工厂 

    2.1.1 springboot启动应用运行run方法

    2.1.2 refreshContext(context);springboot刷新ioc容器【创建ioc容器对象,并初始化容器,创建容器中的每一个组件】;如果是web应用创建AnnotationConfigEmbeddedWebApplicationContext容器,否则创建默认的AnnotationConfigApplicationContext容器

    2.1.3  refresh(context);刷新刚才创建好的ioc容器;

    public void refresh() throws BeansException, IllegalStateException {
            Object var1 = this.startupShutdownMonitor;
            synchronized(this.startupShutdownMonitor) {
                this.prepareRefresh();
                ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
                this.prepareBeanFactory(beanFactory);
    
                try {
                    this.postProcessBeanFactory(beanFactory);
                    this.invokeBeanFactoryPostProcessors(beanFactory);
                    this.registerBeanPostProcessors(beanFactory);
                    this.initMessageSource();
                    this.initApplicationEventMulticaster();
                    this.onRefresh();
                    this.registerListeners();
                    this.finishBeanFactoryInitialization(beanFactory);
                    this.finishRefresh();
                } catch (BeansException var9) {
                    if (this.logger.isWarnEnabled()) {
                        this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                    }
    
                    this.destroyBeans();
                    this.cancelRefresh(var9);
                    throw var9;
                } finally {
                    this.resetCommonCaches();
                }
    
            }
        }

    2.1.4 onRefresh(); web的ioc容器重写了onRefresh()方法;

    2.1.5 web ioc容器创建嵌入式servlet容器: createEmbeddedServletContainer();

    2.1.6 获取嵌入式servlet容器工厂 getEmbeddedServletContainerFactory() =>从容器中获取EmbeddedServletContainerFactory组件

       TomcatEmbeddedServletContainerFactory创建对象,后置处理器一看是这个对象,就获取所有的定制器,先定制servlet容器的相关配置

    2.1.7 使用容器工厂获取嵌入式servlet容器 this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(getSelfInitializer());

    2.1.8 嵌入式servlet容器创建对象并启动ioc容器;

      先启动嵌入式servlet容器,再将ioc容器中没有创建的对象获取出来;ioc容器启动的时候创建嵌入式servlet容器。

  • 相关阅读:
    [Python图像处理]十.图像的灰度线性变换
    pyecharts实现散点图,词云图,饼状图,直方图
    pyecharts(柱状图)
    [Python图像处理]九.图像形态学相关运算
    如何排查内存泄漏
    如何进行SDK的测试
    分享两个实用的shell脚本实例
    分享一个实用脚本--一键获取linux内存、cpu、磁盘IO等信息
    Linux服务器问题排查思路及常用命令
    工作中最常用的Linux命令,排查问题必备
  • 原文地址:https://www.cnblogs.com/hlkawa/p/9736226.html
Copyright © 2011-2022 走看看