Springboot Web应用中服务器配置参数ServerProperties的加载

2022-09-07 08:28:27

#概述

Springboot配置文件中以server开头的项表示服务器的配置参数,这一点从字面意义即可直观理解,这些参数,包括端口,路径设置,SSL配置参数等等。具体有哪些参数,从源代码的角度上,可以参考类ServerProperties的定义,它位于包org.springframework.boot.autoconfigure.web 中。

服务器配置参数的加载,Springboot应用中是通过其自动配置机制来实现的,下面就具体分析其过程。

#自动配置定义服务器配置参数加载工具

EmbeddedServletContainerAutoConfiguration注册bean EmbeddedServletContainerCustomizerBeanPostProcessor

EmbeddedServletContainerAutoConfiguration是Springboot的自动配置类,位于包

package org.springframework.boot.autoconfigure.web

这个配置类以内部类的形式定义了一个ImportBeanDefinitionRegistrar并通过@Import注解导入,而该导入会引起向容器注册一个Bean embeddedServletContainerCustomizerBeanPostProcessor。

// 该代码引用略去与本主题无关部分
@Configuration
@ConditionalOnWebApplication
@Import(BeanPostProcessorsRegistrar.class)//内部类BeanPostProcessorsRegistrar导入
public class EmbeddedServletContainerAutoConfiguration {
	
	// 内部类BeanPostProcessorsRegistrar定义
	public static class BeanPostProcessorsRegistrar
			implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
@Override
		public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
				BeanDefinitionRegistry registry) {
			if (this.beanFactory == null) {
				return;
			}
			// 注册bean embeddedServletContainerCustomizerBeanPostProcessor,
			// 对应类 EmbeddedServletContainerCustomizerBeanPostProcessor.class
			registerSyntheticBeanIfMissing(registry,
					"embeddedServletContainerCustomizerBeanPostProcessor",
					EmbeddedServletContainerCustomizerBeanPostProcessor.class);
		}			
			}
}

关于上面ImportBeanDefinitionRegistrar的执行时机,可以参考 :
ConfigurationClassBeanDefinitionReader 是如何工作的 ?

Bean embeddedServletContainerCustomizerBeanPostProcessor对应类为
EmbeddedServletContainerCustomizerBeanPostProcessor,该类实现了 BeanPostProcessor, BeanFactoryAware 两个接口。

该bean embeddedServletContainerCustomizerBeanPostProcessor的用途是把Bean容器中注册的所有EmbeddedServletContainerCustomizer bean应用到ConfigurableEmbeddedServletContainer。而在基于tomcat的Springboot Web应用中,这里会是一个TomcatEmbeddedServletContainerFactory 。

ServerPropertiesAutoConfiguration定义服务器配置参数加载工具Bean serverProperties

ServerPropertiesAutoConfiguration是Springboot的另外一个自动配置类,位于包

package org.springframework.boot.autoconfigure.web

它定义了bean serverProperties,对应实现类ServerProperties,这是负责加载服务器配置参数的工具类。

// 该代码引用略去与本主题无关部分
@Configuration
@EnableConfigurationProperties
@ConditionalOnWebApplication
public class ServerPropertiesAutoConfiguration {

	// 定义加载服务器配置参数的工具bean
	@Bean
	@ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
	public ServerProperties serverProperties() {
		return new ServerProperties();
	}

ServerProperties读取服务器配置参数

ServerProperties是springboot的自动配置autoconfigure工具,位于包

org.springframework.boot.autoconfigure.web

该类用于提供服务器的端口,路径,SSL等参数设置,它实现了接口EmbeddedServletContainerCustomizer,是专门设计给EmbeddedServletContainerCustomizerBeanPostProcessor用来定制EmbeddedServletContainerFactory实例的。

ServerProperties在容器启动时会被作为bean定义注册到容器,在容器启动过程中应用EmbeddedServletContainerCustomizerBeanPostProcessor的阶段,ServerProperties bean会被实例化,此时配置文件会被该bean读取。

具体的执行入口点如下 :

SpringApplication.run()
 => refreshContext()
  => EmbeddedWebApplicationContext.refresh()
  => onRefresh()  
  => createEmbeddedServletContainer()
  => getEmbeddedServletContainerFactory()
    => AbstractBeanFactory.getBean("tomcatEmbeddedServletContainerFactory")
    => doGetBean()
	=> DefaultSingletonBeanRegistry.getSingleton()    
    => AbstractAutowireCapableBeanFactory.doCreateBean()
    => initializeBean() // 此时Bean已经实例化,并且已经填充能从容器中获得的属性
    => applyBeanPostProcessorsBeforeInitialization()// 此时被已经调用aware方法

上面的方法applyBeanPostProcessorsBeforeInitialization()会在当前bean上面尝试应用所有注册到容器的BeanPostProcessor。

// 实现在 AbstractAutowireCapableBeanFactory 中
// 对existingBean应用所有BeanPostProcessor ,从以下逻辑可以看出,此时尚不区分某个
// BeanPostProcessor对bean existingBean是否可以真正执行,这个判断逻辑,交给具体的
// BeanPostProcessor实现来完成
@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			result = beanProcessor.postProcessBeforeInitialization(result, beanName);
			if (result == null) {
				return result;
			}
		}
		return result;
	}

BeanPostProcessor bean EmbeddedServletContainerCustomizerBeanPostProcessor 发现bean tomcatEmbeddedServletContainerFactory是其目标应用对象,所以就会将自己的方法postProcessBeforeInitialization()针对其执行:

	// 类EmbeddedServletContainerCustomizerBeanPostProcessor的方法实现
	// 类EmbeddedServletContainerCustomizerBeanPostProcessor实现了BeanPostProcessor接口
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		if (bean instanceof ConfigurableEmbeddedServletContainer) {
			postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
		}
		return bean;
	}
	// 将所有的customizer应用到目标bean上
	// 从上面的分析已经知道ServerProperties就是一个
	// EmbeddedServletContainerCustomizer,所以在这个方法执行时,bean serverProperties
	// 会将服务器配置参数设置到目标内置servlet容器
	private void postProcessBeforeInitialization(
			ConfigurableEmbeddedServletContainer bean) {
		for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
			customizer.customize(bean);
		}
	}	
	// 所有的customizer是容器中类别为EmbeddedServletContainerCustomizer的bean定义,
	// 这里获取并实例化它们,从上面的分析已经知道ServerProperties是一个
	// EmbeddedServletContainerCustomizer,所以在下面方法执行时,bean ServerProperties就会被
	// 实例化,相应的服务器配置参数会被加载进来
	private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
		if (this.customizers == null) {
			// Look up does not include the parent context
			this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(
					this.beanFactory
							.getBeansOfType(EmbeddedServletContainerCustomizer.class,
									false, false)
							.values());
			Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
			this.customizers = Collections.unmodifiableList(this.customizers);
		}
		return this.customizers;
	}
  • 作者:安迪源文
  • 原文链接:https://andyboke.blog.csdn.net/article/details/78875973
    更新时间:2022-09-07 08:28:27