首页 > 代码库 > Spring Boot 源码之 内嵌Tomcat端口号赋值逻辑

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()));
    }

 

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