SpringBoot——Servlet容器启动解析

前言

SpringBoot1.x只区分web环境和非web环境,而在2.x版本中引入了Reactive环境,即响应式环境.那么现在SpringBoot支持三种环境:
Servlet的web环境、Reactive的web环境以及非web环境。90%以上的公司使用的是Servlet的web环境,而该环境默认使用的是tomcat容器,本章内容主要就是介绍Servlet容器启动流程。

Tomcat 是什么

Tomcat 是由 Apache 开发的一个 Servlet 容器,实现了对 Servlet 和 JSP 的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等。

由于 Tomcat 本身也内含了一个 HTTP 服务器,它也可以被视作一个单独的 Web 服务器。但是,不能将 Tomcat 和 Apache HTTP 服务器混淆,Apache HTTP 服务器是一个用 C 语言实现的 HTTP Web 服务器;这两个 HTTP web server 不是捆绑在一起的。Tomcat 包含了一个配置管理工具,也可以通过编辑XML格式的配置文件来进行配置。

容器架构
容器处理

启动流程解析

在SpringApplication.run(Application.class,args)里面会构造一个SpringApplication对象,进入其构造函数中

public class SpringApplication {
    private WebApplicationType webApplicationType;

    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        //webApplicationType属性决定了后续容器启动是servlet还是reactive
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
    }
}

public enum WebApplicationType {

    /**
     * The application should not run as a web application and should not start an
     * embedded web server.
     */
    NONE,

    /**
     * The application should run as a servlet-based web application and should start an
     * embedded servlet web server.
     */
    SERVLET,

    /**
     * The application should run as a reactive web application and should start an
     * embedded reactive web server.
     */
    REACTIVE;

    private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
            "org.springframework.web.context.ConfigurableWebApplicationContext" };

    private static final String WEBMVC_INDICATOR_CLASS = "org.springframework." + "web.servlet.DispatcherServlet";

    private static final String WEBFLUX_INDICATOR_CLASS = "org." + "springframework.web.reactive.DispatcherHandler";

    private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

    private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";

    private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";

    //通过判断Classpath路径下是否存在某些特定的类,来决定当前是什么样的环境
    static WebApplicationType deduceFromClasspath() {
        if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
                && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
            return WebApplicationType.REACTIVE;
        }
        for (String className : SERVLET_INDICATOR_CLASSES) {
            if (!ClassUtils.isPresent(className, null)) {
                return WebApplicationType.NONE;
            }
        }
        return WebApplicationType.SERVLET;
    }
}

在SpringApplication的run方法中,context = createApplicationContext()代表创建应用上下文,其就是根据属性webApplicationType来构造什么类

public class SpringApplication {

    /**
     * The class name of application context that will be used by default for non-web
     * environments.
     */
    public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
            + "annotation.AnnotationConfigApplicationContext";

    /**
     * The class name of application context that will be used by default for web
     * environments.
     */
    public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."
            + "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";

    /**
     * The class name of application context that will be used by default for reactive web
     * environments.
     */
    public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework."
            + "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";

    public ConfigurableApplicationContext run(String... args) {
        ......
        try {
            ......
                
            //创建应用上下文
            context = createApplicationContext();
            ......
        }
        catch (Throwable ex) {
            ......
        }

        ......
        return context;
    }

    protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch (this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                    break;
                case REACTIVE:
                    contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                    break;
                default:
                    contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
                }
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
                        ex);
            }
        }
        return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
    }
}

servlet容器启动是在refreshContext(context)方法当中,该方法最终会调用AbstractApplicationContext类中的refresh()方法,该方法会调用onRefresh()方法

private void refreshContext(ConfigurableApplicationContext context) {
    refresh(context);
    if (this.registerShutdownHook) {
        try {
            context.registerShutdownHook();
        }
        catch (AccessControlException ex) {
            // Not allowed in some environments.
        }
    }
}

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        ......

        try {
            ......
            // Initialize other special beans in specific context subclasses.
            onRefresh();

            ......
        }

        catch (BeansException ex) {
            ......
        }

        finally {
            ......
        }
    }
}

onRefresh()方法由子类实现,根据不同的应用上下文去调用不同的方法,这里为Servlet容器环境,所以调用ServletWebServerApplicationContext类中的onRefresh()方法

public class ServletWebServerApplicationContext extends GenericWebApplicationContext
        implements ConfigurableWebServerApplicationContext {
    @Override
    protected void onRefresh() {
        super.onRefresh();
        try {
            //构建web服务器
            createWebServer();
        }
        catch (Throwable ex) {
            throw new ApplicationContextException("Unable to start web server", ex);
        }
    }

    private void createWebServer() {
        // 刚开始这两个属性都为null
        WebServer webServer = this.webServer;
        ServletContext servletContext = getServletContext();
        if (webServer == null && servletContext == null) {
            // 走到这步获取WebServerFactory
            ServletWebServerFactory factory = getWebServerFactory();
            //获取WebServerFactory的具体实现之后,调用getWebServer获取一个具体的WebServer,
            //默认调用TomcatServletWebServerFactory中的getWebServer()方法
            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();
    }

    protected ServletWebServerFactory getWebServerFactory() {
        // Use bean names so that we don't consider the hierarchy
        // 默认返回只有一个,tomcatServletWebServerFactory
        String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
        if (beanNames.length == 0) {
            throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
                    + "ServletWebServerFactory bean.");
        }
        if (beanNames.length > 1) {
            throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
                    + "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
        }
        // 获得BeanFactory后调用getBean创建单例bean
        return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
    }
}
public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory
        implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware {
    // 调用此方法创建webServer
    @Override
    public WebServer getWebServer(ServletContextInitializer... initializers) {
        // 创建一个tomcat
        Tomcat tomcat = new 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);
        return getTomcatWebServer(tomcat);
    }

    protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
        // 这步就创建一个TomcatWebServer,里面还会做一些事情......
        return new TomcatWebServer(tomcat, getPort() >= 0);
    }
}

接着看initPropertySources()方法

protected void initPropertySources() {
    ConfigurableEnvironment env = this.getEnvironment();
    if (env instanceof ConfigurableWebEnvironment) {
        ((ConfigurableWebEnvironment)env).initPropertySources(this.servletContext, (ServletConfig)null);
    }
}

public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
    WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);
}

public static void initServletPropertySources(MutablePropertySources sources, @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
    Assert.notNull(sources, "'propertySources' must not be null");
    String name = "servletContextInitParams";
     // 判断servletContext不为null且包含这个servletContextInitParams属性集
    if (servletContext != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
        // 封装一个ServletContextPropertySource属性集替换原有的
        sources.replace(name, new ServletContextPropertySource(name, servletContext));
    }

    name = "servletConfigInitParams";
    // servletConfig默认为null
    if (servletConfig != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
        sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
    }

}

这样就完成了webServer即Tomcat服务器的创建
在进入AbstractApplicationContext中refresh()方法中的finishRefresh()方法中,该方法会根据web容器的环境进行调用,这里会进入ServletWebServerApplicationContext类中的finishRefresh()方法中

@Override
protected void finishRefresh() {
    super.finishRefresh();
    //启动WebServer
    WebServer webServer = startWebServer();
    if (webServer != null) {
        // 发布Server初始完毕事件
        publishEvent(new ServletWebServerInitializedEvent(webServer, this));
    }
}

private WebServer startWebServer() {
    WebServer webServer = this.webServer;
    if (webServer != null) {
        webServer.start();
    }
    return webServer;
}

@Override
public void start() throws WebServerException {
    synchronized (this.monitor) {
        if (this.started) {
            return;
        }
        try {
            addPreviouslyRemovedConnectors();
            Connector connector = this.tomcat.getConnector();
            if (connector != null && this.autoStart) {
                performDeferredLoadOnStartup();
            }
            checkThatConnectorsHaveStarted();
            this.started = true;
            logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '"
                    + getContextPath() + "'");
        }
        catch (ConnectorStartFailedException ex) {
            stopSilently();
            throw ex;
        }
        catch (Exception ex) {
            throw new WebServerException("Unable to start embedded Tomcat server", ex);
        }
        finally {
            Context context = findContext();
            ContextBindings.unbindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
        }
    }
}
启动前准备
webServer创建入口
servlet启动

web容器工厂类加载解析

默认返回只有一个TomcatServletWebServerFactory,那么这个bean定义什么时候被加载到容器中

String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);

它是通过ConfigurationClassParser类中的parse方法,通过@Import注解导入到容器中的

class ConfigurationClassParser {
    public void parse(Set<BeanDefinitionHolder> configCandidates) {
        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();
            try {
                if (bd instanceof AnnotatedBeanDefinition) {
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                }
                else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                    parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
                }
                else {
                    parse(bd.getBeanClassName(), holder.getBeanName());
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
            }
        }
        // 这边会处理@Import注解导入的配置类
        this.deferredImportSelectorHandler.process();
    }
}
class ConfigurationClassParser {
    private class DeferredImportSelectorHandler {

        public void process() {
            List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
            this.deferredImportSelectors = null;
            try {
                if (deferredImports != null) {
                    DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
                    deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
                    // 排序并依此遍历调用register方法
                    deferredImports.forEach(handler::register);
                    handler.processGroupImports();
                }
            }
            finally {
                this.deferredImportSelectors = new ArrayList<>();
            }
        }

    }
}
class ConfigurationClassParser {
    private class DeferredImportSelectorGroupingHandler {
        private final Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>();

        private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>();

        public void register(DeferredImportSelectorHolder deferredImport) {
            // 这个返回的Selector就是AutoConfigurationImportSelector,这也是@SpringBootApplication上通过@Import注解
            // 导入的Selector. getImportGroup返回的是AutoConfigurationGroup.class
            Class<? extends Group> group = deferredImport.getImportSelector()
                    .getImportGroup();
            // computeIfAbsent就是不存在就创建,这边也是创建一个grouping
            DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
                    (group != null ? group : deferredImport),
                    key -> new DeferredImportSelectorGrouping(createGroup(group)));
            // this.deferredImports.add(deferredImport);
            // 加入到了deferredImports中,List<deferredimportselectorholder> deferredImports = new ArrayList&lt;&gt;()
            grouping.add(deferredImport);
             // 放入到configurationClasses中
            this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
                    deferredImport.getConfigurationClass());
        }
    }
}

deferredImports.forEach(handler::register),这边主要是构造了一个grouping,在下一步进行处理handler.processGroupImports()

public void processGroupImports() {
    for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
        // 下面先分析这个getImports方法
        grouping.getImports().forEach(entry -> {
            ConfigurationClass configurationClass = this.configurationClasses.get(
                    entry.getMetadata());
            try {
                processImports(configurationClass, asSourceClass(configurationClass),
                        asSourceClasses(entry.getImportClassName()), false);
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to process import candidates for configuration class [" +
                                configurationClass.getMetadata().getClassName() + "]", ex);
            }
        });
    }
}

public Iterable<Group.Entry> getImports() {
    // 这边的deferredImports是通过grouping.add(deferredImport)添加进去的
    for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
        this.group.process(deferredImport.getConfigurationClass().getMetadata(),
                deferredImport.getImportSelector());
    }
    return this.group.selectImports();
}

// 两个参数如下图所示,annotationMetadata是主配置类上面的注解
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
    Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
            () -> String.format("Only %s implementations are supported, got %s",
                    AutoConfigurationImportSelector.class.getSimpleName(),
                    deferredImportSelector.getClass().getName()));
    // 下面先分析下这个getAutoConfigurationEntry方法
    AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
            .getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
    this.autoConfigurationEntries.add(autoConfigurationEntry);
    for (String importClassName : autoConfigurationEntry.getConfigurations()) {
        // 接着依次遍历放入到这个map中,Map<string, annotationmetadata> entries = new LinkedHashMap()
        this.entries.putIfAbsent(importClassName, annotationMetadata);
    }
}

这边就到了AutoConfigurationImportSelector类的getAutoConfigurationEntry方法中

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
        AnnotationMetadata annotationMetadata) {
    // 判断是否支持自动配置
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
    // 这个attributes属性就是上图中显示的,用来过滤自动配置类的
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    // 下面分析这个方法,这个就是加载容器中的自动配置类
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    // 去除重复的,方法就是放入set再放入list中
    configurations = removeDuplicates(configurations);
    // 去除掉应该被排除的
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    checkExcludedClasses(configurations, exclusions);
    configurations.removeAll(exclusions);
    // 通过filter过滤,下面分析,过滤完发现只有22个了
    configurations = filter(configurations, autoConfigurationMetadata);
    // 发布一个事件,好像没有做啥关键的
    fireAutoConfigurationImportEvents(configurations, exclusions);
    // 将configurations封装成AutoConfigurationEntry返回
    return new AutoConfigurationEntry(configurations, exclusions);
}

protected boolean isEnabled(AnnotationMetadata metadata) {
    if (getClass() == AutoConfigurationImportSelector.class) {
        // 判断有没有配置这个属性,没有的话默认为true,
        // String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
        return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
    }
    return true;
}

通过filter方法过滤,过滤完发现只有22个了

private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
    long startTime = System.nanoTime();
    String[] candidates = StringUtils.toStringArray(configurations);
    boolean[] skip = new boolean[candidates.length];
    boolean skipped = false;
    for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
        invokeAwareMethods(filter);
        boolean[] match = filter.match(candidates, autoConfigurationMetadata);
        for (int i = 0; i < match.length; i++) {
            if (!match[i]) {
                skip[i] = true;
                candidates[i] = null;
                skipped = true;
            }
        }
    }
    if (!skipped) {
        return configurations;
    }
    List<String> result = new ArrayList<>(candidates.length);
    for (int i = 0; i < candidates.length; i++) {
        if (!skip[i]) {
            result.add(candidates[i]);
        }
    }
    if (logger.isTraceEnabled()) {
        int numberFiltered = configurations.size() - result.size();
        logger.trace("Filtered " + numberFiltered + " auto configuration class in "
                + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
    }
    return new ArrayList<>(result);
}

protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
    // 看一下这个过滤的逻辑,看下图它的实现类大概就知道它是怎样过滤了
    return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}

过滤完之后会发现此时List<String> configurations集合中有29个,其中有一个org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration


@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
        // 会Import一个这个
        ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
        ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
        ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
    ......
}
@Configuration
class ServletWebServerFactoryConfiguration {

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

        @Bean
        public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
            // 这边就会创建一个TomcatServletWebServerFactory
            return new TomcatServletWebServerFactory();
        }

    }
}

到此为止grouping.getImports方法分析完了,它是返回之前加载的29个自动配置类


class ConfigurationClassParser {
    private class DeferredImportSelectorGroupingHandler {
        public void processGroupImports() {
            for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
                grouping.getImports().forEach(entry -> {
                    // 这边这个configurationClass获取的还是主配置类SpringbootApplication
                    ConfigurationClass configurationClass = this.configurationClasses.get(
                            entry.getMetadata());
                    try {
                        processImports(configurationClass, asSourceClass(configurationClass),
                                asSourceClasses(entry.getImportClassName()), false);
                    }
                    catch (BeanDefinitionStoreException ex) {
                        throw ex;
                    }
                    catch (Throwable ex) {
                        throw new BeanDefinitionStoreException(
                                "Failed to process import candidates for configuration class [" +
                                        configurationClass.getMetadata().getClassName() + "]", ex);
                    }
                });
            }
        }
    }
}

web容器个性化配置解析

属性注入

工厂类初始化

BeanPostProcessor方法实现

定制化流程

入口,onRefresh方法中会创建webServer,走到这里

public class ServletWebServerApplicationContext extends GenericWebApplicationContext
        implements ConfigurableWebServerApplicationContext {
    protected ServletWebServerFactory getWebServerFactory() {
        // Use bean names so that we don't consider the hierarchy
        // 默认返回只有一个,tomcatServletWebServerFactory
        String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
        if (beanNames.length == 0) {
            throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
                    + "ServletWebServerFactory bean.");
        }
        if (beanNames.length > 1) {
            throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
                    + "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
        }
        // 调用getBean创建工厂类实例,这边会调用getBean开始创建bean实例对象
        return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
    }
}

在Bean初始化完成之后会遍历BeanFactory中所有的BeanPostProcessor实现,依次调用BeanPostProcessor接口的postProcessBeforeInitialization方法,在创建Web服务的工厂类的时候也会经历这个步骤,这个方法调用点就在AbstractAutowireCapableBeanFactory类中applyBeanPostProcessorsBeforeInitialization()方法

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {
    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            // 通过断点调试可以发现当中有一个WebServerFactoryCustomizerBeanPostProcessor
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }
}

可以看到postProcessBeforeInitialization方法多个实现中有一个WebServerFactoryCustomizerBeanPostProcessor



点击进入WebServerFactoryCustomizerBeanPostProcessor类中的postProcessBeforeInitialization方法

public class WebServerFactoryCustomizerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof WebServerFactory) {
            postProcessBeforeInitialization((WebServerFactory) bean);
        }
        return bean;
    }

    private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
        // 先看下getCustomizers方法
        // 这边lamda表达式的意思就是遍历getCustomizers方法,通过invoke调用每个customizer.cutomize方法定制修改web容器
        LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
                .withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
                .invoke((customizer) -> customizer.customize(webServerFactory));
    }

    private Collection<WebServerFactoryCustomizer<?>> getCustomizers() {
        if (this.customizers == null) {
            // Look up does not include the parent context
            // 获取容器中的所有WebServerFactoryCustomizer
            this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
            this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
            this.customizers = Collections.unmodifiableList(this.customizers);
        }
        return this.customizers;
    }

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

我们在来看下图中第二个定制器,ServletWebServerFactoryCustomizer是怎么注入的呢?


@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
        ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
        ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
        ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {

    // 通过ServletWebServerFactoryAutoConfiguration的bean方法引入到的,
    // 并且赋值serverProperties
    @Bean
    public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
        return new ServletWebServerFactoryCustomizer(serverProperties);
    }
}
//这就是我们在application.properties中修改port,会被赋值到这里,然后定制器就可以取到
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {

    /**
     * Server HTTP port.
     */
    private Integer port;

    /**
     * Network address to which the server should bind.
     */
    private InetAddress address;
    ......
}
// 然后我们再来看invoke((customizer) -> customizer.customize(webServerFactory))这个步骤,这会调用每个定制器的定制方法
// 具体我们看下ServletWebServerFactoryCustomizer的cutomize方法
public class ServletWebServerFactoryCustomizer
        implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {

    private final ServerProperties serverProperties;

    public ServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
        this.serverProperties = serverProperties;
    }

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void customize(ConfigurableServletWebServerFactory factory) {
        PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
        // 这边是lamda表达式,调用factory.setPort进行赋值
        map.from(this.serverProperties::getPort).to(factory::setPort);
        map.from(this.serverProperties::getAddress).to(factory::setAddress);
        map.from(this.serverProperties.getServlet()::getContextPath).to(factory::setContextPath);
        map.from(this.serverProperties.getServlet()::getApplicationDisplayName).to(factory::setDisplayName);
        map.from(this.serverProperties.getServlet()::getSession).to(factory::setSession);
        map.from(this.serverProperties::getSsl).to(factory::setSsl);
        map.from(this.serverProperties.getServlet()::getJsp).to(factory::setJsp);
        map.from(this.serverProperties::getCompression).to(factory::setCompression);
        map.from(this.serverProperties::getHttp2).to(factory::setHttp2);
        map.from(this.serverProperties::getServerHeader).to(factory::setServerHeader);
        map.from(this.serverProperties.getServlet()::getContextParameters).to(factory::setInitParameters);
    }

}

参考:
https://my.oschina.net/liwanghong/blog/3168322

https://www.cnblogs.com/hggen/p/6264475.html

https://www.cnblogs.com/jingmoxukong/p/8258837.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。