#概述
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;
}