上篇文章我们分析了整个应用上下文的更新过程,但是,我们对AnnotationConfigReactiveWebServerApplicationContext应用上下文中跟当前Web环境紧密相关的两个环节还不是很了解,它们分别是:
onRefresh方法在缺省流程逻辑后扩展增加的Web服务器创建逻辑:createWebServerfinishRefresh方法在缺省流程逻辑后扩展增加的Web服务器启动逻辑:startReactiveWebServer
这一篇文章,我们专门来讲解onRefresh中的createWebServer,也就是创建Web服务器的过程逻辑。
首先,我们看应用上下文的方法onRefresh,它实现在基类ReactiveWebServerApplicationContext中:
// ReactiveWebServerApplicationContext 代码片段
@Override
protected void onRefresh() {
// 调用基类缺省的 onRefresh 逻辑,其实为空
super.onRefresh();
// 尝试创建Web服务器
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start reactive web server", ex);
}
}
上面代码中所调用的方法createWebServer实现如下,也实现在基类ReactiveWebServerApplicationContext中:
// ReactiveWebServerApplicationContext 代码片段
private void createWebServer() {
// this.serverManager 变量用来记录一个 ServerManager 对象,
// ServerManager 是 ReactiveWebServerApplicationContext 的内嵌类,
// 一个 ServerManager 对象用来管理一个 Reactive Web Server 和相应的
// HttpHandler,可以理解 ServerManager 是一个包装器,每个 ServerManager
// 包含了一个 WebServer 和一个 HttpHandler 。
// 在应用启动过程中,当前应用上下文对象更新过程中, this.serverManager
// 初始值为 null,正是在该方法 createWebServer 中将其设置为所创建的
// Reactive Web Server 。
ServerManager serverManager = this.serverManager;
if (serverManager == null) {
// 这里创建一个 ServerManager 对象,记录到 this.serverManager
// ServerManager 对象所包含的 :
// 1. WebServer server 通过 getWebServerFactory() 所获取的工厂方法创建
// 2. HttpHandler handler 初始化为一个初始 handler (调用的话会直接抛异常)
this.serverManager = ServerManager.get(getWebServerFactory());
}
// 初始化属性源,缺省实现为空,子类对该方法也没有定制实现
initPropertySources();
}
上面createWebServer方法中有两个要点需要详细分析一下。一个是ServerManager类自身,因为它包装了所创建的Web服务器,所以值得一提。另外一个是getWebServerFactory方法,使用它用来获取Web服务器的工厂方法,我们有必要分析它为创建Web服务器都提供了什么。
1. ServerManager
首先我们来看ServerManager类,它是一个ReactiveWebServerApplicationContext内嵌类,代码如下 :
// ReactiveWebServerApplicationContext 代码片段
/**
* Internal class used to manage the server and the {@link HttpHandler}, taking care
* not to initialize the handler too early.
*/
// 实现了接口 HttpHandler
static final class ServerManager implements HttpHandler {
private final WebServer server;
private volatile HttpHandler handler;
// 使用指定 ReactiveWebServerFactory factory 构建 WebServer this.server
// this.handler 初始化为当前对象的方法 handleUninitialized, 该方法被调用的话
// 会直接抛出异常,它只是用来作为当前对象尚未完全初始化之前的占位符,并不是
// 设计给调用者使用的,调用者随后调用 ServerManager.start 启动一个 Web
// 服务器时,需要提供自己的 HttpHandler 设置给被启动的 ServerManager
// 对象的属性 handler 上
private ServerManager(ReactiveWebServerFactory factory) {
this.handler = this::handleUninitialized;
// 注意这里创建 WebServer 所传递的参数 HttpHandler
// 是当前 ServerManager 实例
this.server = factory.getWebServer(this);
}
// 一个可以赋值给 HttpHandler 类型函数式接口的函数
// 该方法被调用的话 会直接抛出异常,它只是用来作为当前对象尚未完全初始化之前的占位符,
// 并不是设计给调用者使用的
private Mono<Void> handleUninitialized(ServerHttpRequest request, ServerHttpResponse response) {
throw new IllegalStateException("The HttpHandler has not yet been initialized");
}
// 所实现接口 HttpHandler 约定的方法,处理请求写回响应,具体调用委托给了所包含的 this.handler
@Override
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
return this.handler.handle(request, response);
}
public HttpHandler getHandler() {
return this.handler;
}
// 静态工具方法 : 使用指定的 ReactiveWebServerFactory 构建 ServerManager 对象,
public static ServerManager get(ReactiveWebServerFactory factory) {
return new ServerManager(factory);
}
// 静态工具方法 : 获取指定 ServerManager 对象的的 WebServer server 属性
public static WebServer getWebServer(ServerManager manager) {
return (manager != null) ? manager.server : null;
}
// 静态工具方法 : 启动指定的 ServerManager 所包含的 Web 服务器,
// 使用的 HttpHandler 使用 handlerSupplier 所提供的 HttpHandler
public static void start(ServerManager manager, Supplier<HttpHandler> handlerSupplier) {
if (manager != null && manager.server != null) {
manager.handler = handlerSupplier.get();
manager.server.start();
}
}
// 静态工具方法 : 停止指定的 ServerManager 所包含的 Web 服务器,
public static void stop(ServerManager manager) {
if (manager != null && manager.server != null) {
try {
manager.server.stop();
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
}
}
从上面的分析可见,createWebServer创建了一个ServerManager,而该ServerManager包含两个信息:
- 一个通过指定的
ReactiveWebServerFactory创建的WebServer - 一个初始化为
handleUninitialized的HttpHandler,
不过此时所包含的HttpHandler被调用的话会直接抛出异常。实际上,它只是一个占位符,而并非留给调用者使用的,从ServerManager的静态工具方法start来看,稍后WebServer启动时,需要调用者从外部指定自己的HttpHandler以替换该缺省HttpHandler。
在本系列文章的例子应用中,上面的ReactiveWebServerFactory其实是NettyReactiveWebServerFactory(至于为什么是NettyReactiveWebServerFactory,随后会有分析),通过它创建WebServer的过程如下 :
// NettyReactiveWebServerFactory 代码片段
@Override
public WebServer getWebServer(HttpHandler httpHandler) {
// 创建 HttpServer httpServer, HttpServer 属于项目 reactor
HttpServer httpServer = createHttpServer();
// 包装成 NettyWebServer, WebServer 接口针对 Netty 的实现类, 是 Spring 对 reactor HttpServer
// 的封装
// 从上面的分析我们知道,参数 httpHandler 会是一个 ServerManager 实例,它实现了接口
// HttpHandler , 并且包装一个 HttpHandler 实例,所被包装的这个 HttpHandler 实例
// 才是最终处理请求的 HttpHandler。现在创建 WebServer 的过程中虽然使用的是一个 ServerManager
// 实例,但最终处理请求的 HttpHandler 会使用 ServerManager 实例所包装的那个。
ReactorHttpHandlerAdapter handlerAdapter = new ReactorHttpHandlerAdapter(httpHandler);
return new NettyWebServer(httpServer, handlerAdapter, this.lifecycleTimeout);
}
private HttpServer createHttpServer() {
HttpServer server = HttpServer.create();
// 设置服务器监听地址和端口
if (this.resourceFactory != null) {
LoopResources resources = this.resourceFactory.getLoopResources();
Assert.notNull(resources, "No LoopResources: is ReactorResourceFactory not initialized yet?");
server = server.tcpConfiguration(
(tcpServer) -> tcpServer.runOn(resources).addressSupplier(this::getListenAddress));
}
else {
server = server.tcpConfiguration((tcpServer) -> tcpServer.addressSupplier(this::getListenAddress));
}
// SSL 设置,HTTP2 设置
if (getSsl() != null && getSsl().isEnabled()) {
SslServerCustomizer sslServerCustomizer = new SslServerCustomizer(getSsl(), getHttp2(),
getSslStoreProvider());
server = sslServerCustomizer.apply(server);
}
// 压缩设置
if (getCompression() != null && getCompression().getEnabled()) {
CompressionCustomizer compressionCustomizer = new CompressionCustomizer(getCompression());
server = compressionCustomizer.apply(server);
}
server = server.protocol(listProtocols()).forwarded(this.useForwardHeaders);
return applyCustomizers(server);
}
接下来,我们先不急于分析Web服务器的启动,而是看一下创建Web服务器的另外一个要点: 方法getWebServerFactory(),获取创建Web服务器的工厂对象。
2. ReactiveWebServerFactory getWebServerFactory()
方法getWebServerFactory代码实现如下 :
// ReactiveWebServerApplicationContext 代码片段
protected ReactiveWebServerFactory getWebServerFactory() {
// Use bean names so that we don't consider the hierarchy
// 从容器中获取类型为 ReactiveWebServerFactory 的所有 bean 的名称
String[] beanNames = getBeanFactory().getBeanNamesForType(ReactiveWebServerFactory.class);
if (beanNames.length == 0) {
// 如果容器中不存在类型为 ReactiveWebServerFactory 的 bean,则直接抛出异常,
// 换句话讲,容器中必须要通过某种方式已经注册了类型为 ReactiveWebServerFactory 的 bean
throw new ApplicationContextException(
"Unable to start ReactiveWebApplicationContext due to missing "
+ "ReactiveWebServerFactory bean.");
}
if (beanNames.length > 1) {
// 如果容器中存在多个类型为 ReactiveWebServerFactory 的 bean,则也直接抛出异常,
// 换句话讲,容器中必须要有且仅有一个类型为 ReactiveWebServerFactory 的 bean
throw new ApplicationContextException(
"Unable to start ReactiveWebApplicationContext due to multiple "
+ "ReactiveWebServerFactory beans : "
+ StringUtils.arrayToCommaDelimitedString(beanNames));
}
// 容器中有且仅有一个类型为 ReactiveWebServerFactory 的 bean , 现在获取并返回它
return getBeanFactory().getBean(beanNames[0], ReactiveWebServerFactory.class);
}
方法getWebServerFactory的实现逻辑不难理解,它要求容器中有且仅有一个类型为ReactiveWebServerFactory的bean。如果不是这样,则它会抛出异常;如果是这样,它会获取该ReactiveWebServerFactory bean供调用者用于创建相应的Web服务器。那么,问题来了,我们之前分析启动过程中并没有遇到过该ReactiveWebServerFactory bean的注册,但是getWebServerFactory方又确实能够发现容器中存在ReactiveWebServerFactory bean,这又是为什么呢 ? 这里,我们就不得不考虑Spring Boot的自动配置机制了。实际上,ReactiveWebServerFactory bean之所以存在,正是因为Spring Boot的自动配置机制ReactiveWebServerFactoryAutoConfiguration。
3. ReactiveWebServerFactoryAutoConfiguration自动配置
package org.springframework.boot.autoconfigure.web.reactive;
// 省略 import 行
/**
* {@link EnableAutoConfiguration Auto-configuration} for a reactive web server.
*
* @author Brian Clozel
* @since 2.0.0
*/
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
// 仅在类 ReactiveHttpInputMessage 存在于 classpath 上时生效,
// 这是 spring-web 包内针对 Reactive Web 服务的一个接口类,
// 在我们的例子应用中,显然它是存在于 classpath 上的
@ConditionalOnClass(ReactiveHttpInputMessage.class)
// 仅在当前Web环境是 REACTIVE 时才生效,之前的分析可以表明,
// 我们的例子应用就是这种情况
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
// 将前缀为 server 的配置参数加载到类型为 ServerProperties 的bean
@EnableConfigurationProperties(ServerProperties.class)
// 1. 导入 BeanPostProcessorsRegistrar, BeanPostProcessorsRegistrar 是 ReactiveWebServerFactoryAutoConfiguration
// 内嵌定义的一个 ImportBeanDefinitionRegistrar, 它向容器注册一个 WebServerFactoryCustomizerBeanPostProcessor,
// WebServerFactoryCustomizerBeanPostProcessor 作为一个 BeanPostProcessor , 用于在 WebServerFactory 对象创建时
// 将容器中所有的 WebServerFactoryCustomizer 应用到 WebServerFactory bean 对象
// 2. 导入 ReactiveWebServerFactoryConfiguration 配置中定义的配置子类 EmbeddedTomcat, EmbeddedJetty,
// EmbeddedUndertow,EmbeddedNetty。这4个配置子类会检测相应Web服务器实现的特征类,从而定义相应的
// ReactiveWebServerFactory 到容器。这就是我们上面分析中提到的创建Web服务器所需要的 ReactiveWebServerFactory bean。
// 在本系列文章的例子应用中,其实这4个配置中生效的只有 EmbeddedNetty,相应的 ReactiveWebServerFactory bean
// 实现类实际为 NettyReactiveWebServerFactory
@Import({ ReactiveWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ReactiveWebServerFactoryConfiguration.EmbeddedTomcat.class,
ReactiveWebServerFactoryConfiguration.EmbeddedJetty.class,
ReactiveWebServerFactoryConfiguration.EmbeddedUndertow.class,
ReactiveWebServerFactoryConfiguration.EmbeddedNetty.class })
public class ReactiveWebServerFactoryAutoConfiguration {
// 注册一个 ReactiveWebServerFactoryCustomizer bean 到容器,
// 该 ReactiveWebServerFactoryCustomizer bean 其实是将配置参数设置到 ReactiveWebServerFactory bean 上,
// 它会被 BeanPostProcessorsRegistrar 所注册的 BeanPostProcessor WebServerFactoryCustomizerBeanPostProcessor
// 使用,具体应用点在 ReactiveWebServerFactory bean 创建时
@Bean
public ReactiveWebServerFactoryCustomizer reactiveWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new ReactiveWebServerFactoryCustomizer(serverProperties);
}
/**
* Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via
* {@link ImportBeanDefinitionRegistrar} for early registration.
*/
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, "webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.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);
}
}
}
}
从上面分析可见,ReactiveWebServerFactoryAutoConfiguration自动配置类在条件满足时做了如下事情 :
- 将前缀为
server的配置参数加载到类型为ServerProperties的bean; - 定义一个
bean ReactiveWebServerFactoryCustomizer,该bean的作用时应用于某个WebServerFactory bean,将ServerProperties参数(实际上是上面提到的ServerProperties bean)中的参数设置到WebServerFactory bean;这些信息包括: 端口号参数,主机地址参数,SSL配置参数,压缩参数,HTTP2启用参数; - 导入
BeanPostProcessorsRegistrar,进而向容器注册BeanPostProcessor WebServerFactoryCustomizerBeanPostProcessor,该BeanPostProcessor用于在WebServerFactory对象创建时将容器中所有的WebServerFactoryCustomizer应用到WebServerFactory bean; - 导入
ReactiveWebServerFactoryConfiguration自身定义的配置子类EmbeddedTomcat,EmbeddedJetty,EmbeddedUndertow,EmbeddedNetty。这4个配置子类会检测相应Web服务器实现的特征类,从而定义相应的ReactiveWebServerFactory到容器。这就是我们上面分析中提到的创建Web服务器所需要的ReactiveWebServerFactory bean。在本系列文章的例子应用中,其实这4个配置中生效的只有EmbeddedNetty,相应的ReactiveWebServerFactory bean实现类实际为NettyReactiveWebServerFactory,相应地,它最终所创建WebServer实现类使用NettyWebServer。
下面,给出ReactiveWebServerFactoryConfiguration的源代码,它包含了以上提到的4个配置子类供参考:
package org.springframework.boot.autoconfigure.web.reactive;
// 省略 import 行
abstract class ReactiveWebServerFactoryConfiguration {
// 在 reactor.netty.http.server.HttpServer 存在于 classpath 时生效
// 定义 bean :
// 1. ReactorResourceFactory reactorServerResourceFactory
// 2. NettyReactiveWebServerFactory nettyReactiveWebServerFactory
@Configuration
@ConditionalOnMissingBean(ReactiveWebServerFactory.class)
@ConditionalOnClass({ HttpServer.class })
static class EmbeddedNetty {
@Bean
@ConditionalOnMissingBean
public ReactorResourceFactory reactorServerResourceFactory() {
return new ReactorResourceFactory();
}
@Bean
public NettyReactiveWebServerFactory nettyReactiveWebServerFactory(
ReactorResourceFactory resourceFactory) {
NettyReactiveWebServerFactory serverFactory = new NettyReactiveWebServerFactory();
serverFactory.setResourceFactory(resourceFactory);
return serverFactory;
}
}
@Configuration
@ConditionalOnMissingBean(ReactiveWebServerFactory.class)
@ConditionalOnClass({ org.apache.catalina.startup.Tomcat.class })
static class EmbeddedTomcat {
@Bean
public TomcatReactiveWebServerFactory tomcatReactiveWebServerFactory() {
return new TomcatReactiveWebServerFactory();
}
}
@Configuration
@ConditionalOnMissingBean(ReactiveWebServerFactory.class)
@ConditionalOnClass({ org.eclipse.jetty.server.Server.class })
static class EmbeddedJetty {
@Bean
@ConditionalOnMissingBean
public JettyResourceFactory jettyServerResourceFactory() {
return new JettyResourceFactory();
}
@Bean
public JettyReactiveWebServerFactory jettyReactiveWebServerFactory(
JettyResourceFactory resourceFactory) {
JettyReactiveWebServerFactory serverFactory = new JettyReactiveWebServerFactory();
serverFactory.setResourceFactory(resourceFactory);
return serverFactory;
}
}
@Configuration
@ConditionalOnMissingBean(ReactiveWebServerFactory.class)
@ConditionalOnClass({ Undertow.class })
static class EmbeddedUndertow {
@Bean
public UndertowReactiveWebServerFactory undertowReactiveWebServerFactory() {
return new UndertowReactiveWebServerFactory();
}
}
}
总结
从上面的分析可见,方法createWebServer创建了Web服务器WebServer,包装在一个ServerManager中。所创建的WebServer是由容器中的一个ReactiveWebServerFactory bean来创建的,此ReactiveWebServerFactory bean由Spring Boot自动配置类ReactiveWebServerFactoryAutoConfiguration定义,在本文章例子项目中,实际上是NettyReactiveWebServerFactory。并且该ReactiveWebServerFactory bean在创建时会被设置配置文件中所指定的参数:端口号参数,主机地址参数,SSL配置参数,压缩参数,HTTP2启用参数。
本文解析了在Spring Boot应用中,如何通过ReactiveWebServerApplicationContext创建Web服务器的过程,涉及ServerManager类的使用,以及ReactiveWebServerFactoryAutoConfiguration自动配置机制。
2350

被折叠的 条评论
为什么被折叠?



