SpringBoot嵌入式servlet容器启动原理

转载自caychen的博客SpringBoot嵌入式servlet容器启动原理
从源码的角度分析SpringBoot内嵌的servlet容器是怎么启动的

  1. Spring Boot应用启动运行run方法:
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    FailureAnalyzers analyzers = null;
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
                                                                 applicationArguments);
        Banner printedBanner = printBanner(environment);
        
        //创建一个ApplicationContext容器
        context = createApplicationContext();
        analyzers = new FailureAnalyzers(context);
        prepareContext(context, environment, listeners, applicationArguments,
                       printedBanner);
        //刷新IOC容器
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        listeners.finished(context, null);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
        }
        return context;
    }
    catch (Throwable ex) {
        handleRunFailure(context, listeners, analyzers, ex);
        throw new IllegalStateException(ex);
    }
}
  1. createApplicationContext();创建IOC容器,如果是web应用,则创建AnnotationConfigEmbeddedWebApplicationContext的IOC容器;如果不是,则创建AnnotationConfigApplicationContext的IOC容器:
public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
			+ "annotation.AnnotationConfigApplicationContext";
 
public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework."
			+ "boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext";
 
//SpringApplication#createApplicationContext
protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    if (contextClass == null) {
        try {
            //根据应用环境,创建不同的IOC容器
            contextClass = Class.forName(this.webEnvironment
                                         ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                "Unable create a default ApplicationContext, "
                + "please specify an ApplicationContextClass",
                ex);
        }
    }
    return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
  1. refreshContext(context);Spring Boot刷新IOC容器【创建IOC容器对象,并初始化容器,创建容器中每一个组件】:
//SpringApplication#refreshContext
private void refreshContext(ConfigurableApplicationContext context) {
    refresh(context);
   
    //Other code...
}
  1. refresh(context);刷新刚才创建的IOC容器:
//SpringApplication#refresh
protected void refresh(ApplicationContext applicationContext) {
    Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
    ((AbstractApplicationContext) applicationContext).refresh();
}
  1. 调用抽象父类的refresh()方法:
//AbstractApplicationContext#refresh
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();
 
        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
 
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);
 
        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);
 
            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);
 
            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
 
            // Initialize message source for this context.
            initMessageSource();
 
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();
 
            // Initialize other special beans in specific context subclasses.
            onRefresh();
 
            // Check for listener beans and register them.
            registerListeners();
 
            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);
 
            // Last step: publish corresponding event.
            finishRefresh();
        }
 
        catch (BeansException ex) {
           //...
        }
 
        finally {
            //...
        }
    }
}
  1. 抽象父类AbstractApplicationContext类的子类EmbeddedWebApplicationContext的onRefresh方法:
//EmbeddedWebApplicationContext#onRefresh
@Override
protected void onRefresh() {
    super.onRefresh();
    try {
        createEmbeddedServletContainer();
    }
    catch (Throwable ex) {
        throw new ApplicationContextException("Unable to start embedded container",
                                              ex);
    }
}
  1. 在createEmbeddedServletContainer方法中会获取嵌入式的Servlet容器工厂,并通过工厂来获取Servlet容器:
//EmbeddedWebApplicationContext#createEmbeddedServletContainer
private void createEmbeddedServletContainer() {
    EmbeddedServletContainer localContainer = this.embeddedServletContainer;
    ServletContext localServletContext = getServletContext();
    if (localContainer == null && localServletContext == null) {
        //获取嵌入式Servlet容器工厂
        EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
        //根据容器工厂来获取对应的嵌入式Servlet容器
        this.embeddedServletContainer = containerFactory
            .getEmbeddedServletContainer(getSelfInitializer());
    }
    else if (localServletContext != null) {
        try {
            getSelfInitializer().onStartup(localServletContext);
        }
        catch (ServletException ex) {
            throw new ApplicationContextException("Cannot initialize servlet context",
                                                  ex);
        }
    }
    initPropertySources();
}
  1. 从IOC容器中获取嵌入式Servlet容器工厂:
//EmbeddedWebApplicationContext#getEmbeddedServletContainerFactory
protected EmbeddedServletContainerFactory getEmbeddedServletContainerFactory() {
    // Use bean names so that we don't consider the hierarchy
    String[] beanNames = getBeanFactory()
        .getBeanNamesForType(EmbeddedServletContainerFactory.class);
    if (beanNames.length == 0) {
        throw new ApplicationContextException(
            "Unable to start EmbeddedWebApplicationContext due to missing "
            + "EmbeddedServletContainerFactory bean.");
    }
    if (beanNames.length > 1) {
        throw new ApplicationContextException(
            "Unable to start EmbeddedWebApplicationContext due to multiple "
            + "EmbeddedServletContainerFactory beans : "
            + StringUtils.arrayToCommaDelimitedString(beanNames));
    }
    return getBeanFactory().getBean(beanNames[0],
                                    EmbeddedServletContainerFactory.class);
}

在上文中解释到,如果加入了嵌入式的Servlet容器依赖,Spring Boot就会自动配置一个嵌入式Servlet容器工厂。接着就使用后置处理器,来获取所有的定制器来定制配置,所以上述源码中会从IOC容器中获取EmbeddedServletContainerFactory类型的容器工厂,并返回。

  1. 使用Servlet容器工厂获取嵌入式的Servlet容器,具体使用哪个容器工厂需要看配置环境依赖:
this.embeddedServletContainer = containerFactory
            .getEmbeddedServletContainer(getSelfInitializer());

获取嵌入式的Servlet容器后,会自动启动Servlet容器。

  1. 上述过程是首先启动IOC容器,接着启动嵌入式的Servlet容器,再接着将IOC容器中剩下没有创建的对象获取出来,比如自己创建的controller等等:
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

看看finishBeanFactoryInitialization方法:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    //other code...
 
    // Instantiate all remaining (non-lazy-init) singletons.
    beanFactory.preInstantiateSingletons();
}

大概看看preInstantiateSingletons方法:

@Override
public void preInstantiateSingletons() throws BeansException {
   
    List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
 
    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                    isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                        @Override
                        public Boolean run() {
                            return ((SmartFactoryBean<?>) factory).isEagerInit();
                        }
                    }, getAccessControlContext());
                }
                else {
                    isEagerInit = (factory instanceof SmartFactoryBean &&
                                   ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                    getBean(beanName);
                }
            }
            else {
                //注册bean
                getBean(beanName);
            }
        }
    }
 
    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/m0_37556444/article/details/84864221