SpringBoot 2.x 嵌入式Servlet 启动原理

嵌入式Servlet 启动原理

1)SpringBoot 应用运行run() 方法

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}                 |
	                 \|/
	                  |
 public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}

2) run()内

  • context = createApplicationContext();
    • 【创建IOC对象】
    • 如果是web应用 创建AnnotationConfigServletWebServerApplicationContext容器 或者 AnnotationConfigServletWebServerApplicationContext容器
  • 否则创建AnnotationConfigApplicationContext 容器
  • refreshContext(context);
  • 【 刷新IOC容器, 初始化容器,创建容器中的每一个组件】

3) refresh(context); 刷新刚刚创建创建的容器

   public void refresh() throws BeansException, IllegalStateException {
        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();
            }

        }
    }

4) onRefresh();

  • web Ioc 重写了该方法
   @Override
  protected void onRefresh() {
  	super.onRefresh();
  	try {
  		createWebServer();
  	}
  	catch (Throwable ex) {
  		throw new ApplicationContextException("Unable to start web server", ex);
  	}
  }

5)createWebServer();

  • 创建嵌入式Servlet容器
   private void createWebServer() {
   	WebServer webServer = this.webServer;
   	ServletContext servletContext = getServletContext();
   	if (webServer == null && servletContext == null) {
   		ServletWebServerFactory factory = getWebServerFactory();
   		this.webServer = factory.getWebServer(getSelfInitializer());
   	}
   	else if (servletContext != null) {
   		try {
   			getSelfInitializer().onStartup(servletContext);
   		}
   		catch (ServletException ex) {
   			throw new ApplicationContextException("Cannot initialize servlet context", ex);
   		}
   	}
   	initPropertySources();
   }

6) ServletWebServerFactory factory = getWebServerFactory();

  • 获取嵌入式servlet容器工厂
  • 从容器中获取ServletWebServerFactory组件
  • TomcatServletWebServerFactory创建对象
  • 后置处理器进行判断,如果是webServerFactory 类对象,获取所有的Customizer【Customizer对象在此创建】,并调用其customize(),完成servlet相关配置
  @Override
 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 	//如果是webServerFactory 类对象,获取所有的Customizer
 	if (bean instanceof WebServerFactory) {
 		postProcessBeforeInitialization((WebServerFactory) bean);
 	}
 	return bean;
 }
 private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
 	LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
 	.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
 	.invoke((customizer) -> customizer.customize(webServerFactory));
 }

7) this.webServer = factory.getWebServer(getSelfInitializer());

  • 使用Servlet 容器工厂 获取嵌入式Servlet 容器
  • 嵌入式Servlet 容器 创建对象(此处为tomcat),并启动
public WebServer getWebServer(ServletContextInitializer... initializers) {
      return getTomcatWebServer(tomcat);
  }
  
  protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
  	return new TomcatWebServer(tomcat, getPort() >= 0);
  }
  
  public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
  	Assert.notNull(tomcat, "Tomcat Server must not be null");
  	this.tomcat = tomcat;
  	this.autoStart = autoStart;
  	initialize();
  }
  private void initialize() throws WebServerException {
      this.tomcat.start();
  }

8)先启动嵌入式的Servlet容器,再将Ioc容器中没有创建的对象获取出来

发布了47 篇原创文章 · 获赞 7 · 访问量 2349

猜你喜欢

转载自blog.csdn.net/qq_43616898/article/details/104161145