Spring Boot 源码之 内嵌Tomcat端口号赋值逻辑

一、Cumtomizer的Bean的定义

EmbeddedServletContainerAutoConfiguration.java

在处理自动配置的时候,扫描到这个Bean,注册到了BeanFactory里面

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import(BeanPostProcessorsRegistrar.class)
public class EmbeddedServletContainerAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public DefaultServletContainerCustomizer serverPropertiesServletContainerCustomizer(
            ServerProperties serverProperties) {
        return new DefaultServletContainerCustomizer(serverProperties);
    }

二、对应BeanPostProcessor的添加

EmbeddedServletContainerAutoConfiguration.java

因为@Import(BeanPostProcessorsRegistrar.class),所以在processImport的时候实例化了一个BeanPostProcessorsRegistrar对象

else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                        // Candidate class is an ImportBeanDefinitionRegistrar ->
                        // delegate to it to register additional bean definitions
                        Class<?> candidateClass = candidate.loadClass();
                        ImportBeanDefinitionRegistrar registrar =
                                BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
                        ParserStrategyUtils.invokeAwareMethods(
                                registrar, this.environment, this.resourceLoader, this.registry);
                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                    }

然后后面调用了它的registerBeanDefinitions方法:

    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());

    private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
        for (Map.Entry<ImportBeanDefinitionRegistrar, AnnotationMetadata> entry : registrars.entrySet()) {
            entry.getKey().registerBeanDefinitions(entry.getValue(), this.registry);
        }
    }

然后EmbeddedServletContainerCustomizerBeanPostProcessor被注册到了BeanFactory

    public static class BeanPostProcessorsRegistrar
            implements ImportBeanDefinitionRegistrar, BeanFactoryAware {

        private ConfigurableListableBeanFactory beanFactory;

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

        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                BeanDefinitionRegistry registry) {
            if (this.beanFactory == null) {
                return;
            }
            registerSyntheticBeanIfMissing(registry,
                    "embeddedServletContainerCustomizerBeanPostProcessor",
                    EmbeddedServletContainerCustomizerBeanPostProcessor.class);
            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);
            }
        }

    }

三、TomcatEmbeddedServletContainerFactory对应的Bean实例化的时候触发BeanPostProcessor如下的处理:

postProcessBeforeInitialization方法 从BeanFactory里面找到
DefaultServletContainerCustomizer ,然后调用它的cumtomize方法处理TomcatEmbeddedServletContainerFactory
public class EmbeddedServletContainerCustomizerBeanPostProcessor
        implements BeanPostProcessor, BeanFactoryAware {

    private ListableBeanFactory beanFactory;

    private List<EmbeddedServletContainerCustomizer> customizers;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
                "EmbeddedServletContainerCustomizerBeanPostProcessor can only be used "
                        + "with a ListableBeanFactory");
        this.beanFactory = (ListableBeanFactory) beanFactory;
    }

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

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        return bean;
    }

    private void postProcessBeforeInitialization(
            ConfigurableEmbeddedServletContainer bean) {
        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<>(this.beanFactory.getBeansOfType(
                    EmbeddedServletContainerCustomizer.class, false, false).values());
            Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
            this.customizers = Collections.unmodifiableList(this.customizers);
        }
        return this.customizers;
    }

}

四、custom的处理

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        if (this.serverProperties.getPort() != null) {
            container.setPort(this.serverProperties.getPort());
        }
        if (this.serverProperties.getAddress() != null) {
            container.setAddress(this.serverProperties.getAddress());
        }
        if (this.serverProperties.getServlet().getContextPath() != null) {
            container.setContextPath(this.serverProperties.getServlet().getContextPath());
        }
        if (this.serverProperties.getDisplayName() != null) {
            container.setDisplayName(this.serverProperties.getDisplayName());
        }
        if (this.serverProperties.getSession().getTimeout() != null) {
            container.setSessionTimeout(this.serverProperties.getSession().getTimeout());
        }
        container.setPersistSession(this.serverProperties.getSession().isPersistent());
        container.setSessionStoreDir(this.serverProperties.getSession().getStoreDir());
        if (this.serverProperties.getSsl() != null) {
            container.setSsl(this.serverProperties.getSsl());
        }
        if (this.serverProperties.getServlet() != null) {
            container.setJsp(this.serverProperties.getServlet().getJsp());
        }
        if (this.serverProperties.getCompression() != null) {
            container.setCompression(this.serverProperties.getCompression());
        }
        container.setServerHeader(this.serverProperties.getServerHeader());
        if (container instanceof TomcatEmbeddedServletContainerFactory) {
            TomcatCustomizer.customizeTomcat(this.serverProperties, this.environment,
                    (TomcatEmbeddedServletContainerFactory) container);
        }
        if (container instanceof JettyEmbeddedServletContainerFactory) {
            JettyCustomizer.customizeJetty(this.serverProperties, this.environment,
                    (JettyEmbeddedServletContainerFactory) container);
        }

        if (container instanceof UndertowEmbeddedServletContainerFactory) {
            UndertowCustomizer.customizeUndertow(this.serverProperties, this.environment,
                    (UndertowEmbeddedServletContainerFactory) container);
        }
        container.addInitializers(
                new SessionConfiguringInitializer(this.serverProperties.getSession()));
        container.addInitializers(new InitParameterConfiguringServletContextInitializer(
                this.serverProperties.getServlet().getContextParameters()));
    }
时间: 2024-10-25 10:12:37

Spring Boot 源码之 内嵌Tomcat端口号赋值逻辑的相关文章

spring boot 启动web,内嵌tomcat

1.pom.xml文件配置(酌情修改) <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"

曹工说Spring Boot源码(13)-- AspectJ的运行时织入(Load-Time-Weaving),基本内容是讲清楚了(附源码)

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

Spring Boot源码中模块详解

Spring Boot源码中模块详解 一.源码 spring boot2.1版本源码地址:https://github.com/spring-projects/spring-boot/tree/2.1.x 二.模块 Spring Boot 包含许多模块,以下是一些简单的概述: 1,spring-boot 为Spring Boot其他部分功能提供主要的lib包,其中包含:(1)SpringApplication类提供了静态便利的方法使编写独立的SpringApplication更加容易.它唯一的任

曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean definition的?

写在前面的话 相关背景及资源: 曹工说Spring Boot源码系列开讲了(1)-- Bean Definition到底是什么,附spring思维导图分享 工程代码地址 思维导图地址 工程结构图: 大体思路 总体来说,bean definition是什么,我们前面几讲,说了个大概了:目前,我们将聚焦于怎么获取bean definition. 我们这次做个实验,就是将bean definition(一共两个bean,有依赖关系,依赖是手动指定的)定义在json文件内,然后自定义一个applicat

曹工说Spring Boot源码(5)-- 怎么从properties文件读取bean

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

曹工说Spring Boot源码(6)-- Spring怎么从xml文件里解析bean的

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

曹工说Spring Boot源码(9)-- Spring解析xml文件,到底从中得到了什么(context命名空间上)

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

曹工说Spring Boot源码(15)-- Spring从xml文件里到底得到了什么(context:load-time-weaver 完整解析)

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de

曹工说Spring Boot源码(16)-- Spring从xml文件里到底得到了什么(aop:config完整解析【上】)

写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解 曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean de