一,加载REACTIVE相关自动配置

spring boot通过判断含org.springframework.web.reactive.DispatcherHandler字节文件就确定程序类型是REACTIVE,然后加载上下文类org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext,看下面代码
private WebApplicationType deduceWebApplicationType() {
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.server.ResourceConfig", (ClassLoader)null)) {
return WebApplicationType.REACTIVE;
} else {
String[] var1 = WEB_ENVIRONMENT_CLASSES;
int var2 = var1.length; for(int var3 = 0; var3 < var2; ++var3) {
String className = var1[var3];
if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
return WebApplicationType.NONE;
}
} return WebApplicationType.SERVLET;
}
}

当程序类型是REACTIVE,spring boot首先就会加载自身的自动配置类org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration。如果找到HttpServer.clas而且又没有自己实现的ReactiveWebServerFactory.class就应用spring boot自带的nettyReactiveWebServerFactory对象。如果会用jetty或tomcat就引用有Server.class或Tomcat.class第三方包。

@AutoConfigureOrder(-2147483648)
@Configuration
@ConditionalOnClass({ReactiveHttpInputMessage.class})
@ConditionalOnWebApplication(
type = Type.REACTIVE
)
@EnableConfigurationProperties({ServerProperties.class})
@Import({ReactiveWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class, EmbeddedNetty.class})
public class ReactiveWebServerFactoryAutoConfiguration {
public ReactiveWebServerFactoryAutoConfiguration() {
} ...................................... abstract class ReactiveWebServerFactoryConfiguration {
ReactiveWebServerFactoryConfiguration() {
} @Configuration
@ConditionalOnMissingBean({ReactiveWebServerFactory.class})
@ConditionalOnClass({HttpServer.class})
static class EmbeddedNetty {
EmbeddedNetty() {
} @Bean
public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() {
return new NettyReactiveWebServerFactory();
}
}

应用程序没有提供WebFluxConfigurationSupport的实例,spring boot就会加载自身的自动配置类org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration。加载对象有webHandler(org.springframework.web.reactive.DispatcherHandler)等

@Configuration
@ConditionalOnWebApplication(
type = Type.REACTIVE
)
@ConditionalOnClass({WebFluxConfigurer.class})
@ConditionalOnMissingBean({WebFluxConfigurationSupport.class})
@AutoConfigureAfter({ReactiveWebServerFactoryAutoConfiguration.class, CodecsAutoConfiguration.class, ValidationAutoConfiguration.class})
@AutoConfigureOrder(-2147483638)
public class WebFluxAutoConfiguration {

应用程序没有提供HttpHandler的实例,spring boot就会加载自身的自动配置类org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,加载对象httpHandler(org.springframework.web.server.adapter.HttpWebHandlerAdapter)。

@Configuration
@ConditionalOnClass({DispatcherHandler.class, HttpHandler.class})
@ConditionalOnWebApplication(
type = Type.REACTIVE
)
@ConditionalOnMissingBean({HttpHandler.class})
@AutoConfigureAfter({WebFluxAutoConfiguration.class})
@AutoConfigureOrder(-2147483638)
public class HttpHandlerAutoConfiguration {
public HttpHandlerAutoConfiguration() {
} @Configuration
public static class AnnotationConfig {
private ApplicationContext applicationContext; public AnnotationConfig(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
} @Bean
public HttpHandler httpHandler() {
return WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();
}
}
}

二,创建REACTIVE内嵌服务器

WebServer在org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext创建。依赖的HttpHandler实例上面已说明如果创建的。

org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext

   protected void onRefresh() {
super.onRefresh(); try {
this.createWebServer();
} catch (Throwable var2) {
throw new ApplicationContextException("Unable to start reactive web server", var2);
}
} private void createWebServer() {
  WebServer localServer = this.webServer;
  if (localServer == null) {
  this.webServer = this.getWebServerFactory().getWebServer(this.getHttpHandler());
  }   this.initPropertySources();
}
org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory

    public WebServer getWebServer(HttpHandler httpHandler) {
HttpServer httpServer = this.createHttpServer();
ReactorHttpHandlerAdapter handlerAdapter = new ReactorHttpHandlerAdapter(httpHandler);
return new NettyWebServer(httpServer, handlerAdapter, this.lifecycleTimeout);
}

三,Annotated Controllers与Functional Endpoints

spring webflux处理http请求有两种编程模式,分别是annotated controllers和functional endpoints,annotated controllers与spring mvc类似。它们都调用HttpHandler实现org.springframework.web.server.adapter.HttpWebHandlerAdapter的handle方法。

handle:183, HttpWebHandlerAdapter (org.springframework.web.server.adapter)
apply:75, ReactorHttpHandlerAdapter (org.springframework.http.server.reactive)
apply:40, ReactorHttpHandlerAdapter (org.springframework.http.server.reactive)
applyHandler:380, ChannelOperations (reactor.ipc.netty.channel)
onHandlerStart:407, HttpServerOperations (reactor.ipc.netty.http.server)
run:-1, 1927250759 (reactor.ipc.netty.channel.ContextHandler$$Lambda$524)
safeExecute$$$capture:163, AbstractEventExecutor (io.netty.util.concurrent)
safeExecute:-1, AbstractEventExecutor (io.netty.util.concurrent)
- Async stack trace
addTask:-1, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:765, SingleThreadEventExecutor (io.netty.util.concurrent)
createOperations:249, ContextHandler (reactor.ipc.netty.channel)
channelRead:136, HttpServerHandler (reactor.ipc.netty.http.server)
invokeChannelRead:362, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:348, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:340, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:438, CombinedChannelDuplexHandler$DelegatingChannelHandlerContext (io.netty.channel)
fireChannelRead:310, ByteToMessageDecoder (io.netty.handler.codec)
channelRead:284, ByteToMessageDecoder (io.netty.handler.codec)
channelRead:253, CombinedChannelDuplexHandler (io.netty.channel)
invokeChannelRead:362, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:348, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:340, AbstractChannelHandlerContext (io.netty.channel)
channelRead:1434, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeChannelRead:362, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:348, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:965, DefaultChannelPipeline (io.netty.channel)
read:163, AbstractNioByteChannel$NioByteUnsafe (io.netty.channel.nio)
processSelectedKey:628, NioEventLoop (io.netty.channel.nio)
processSelectedKeysOptimized:563, NioEventLoop (io.netty.channel.nio)
processSelectedKeys:480, NioEventLoop (io.netty.channel.nio)
run:442, NioEventLoop (io.netty.channel.nio)
run:884, SingleThreadEventExecutor$5 (io.netty.util.concurrent)
run:745, Thread (java.lang)

他们也调用handle:149, DispatcherHandler (org.springframework.web.reactive),但最后他们分别调用BookController或BookHandler,看下面不同调用栈:

annotated controllers
getBookById:19, BookController (com.javaworld.webflux.bookservice.web)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
doInvoke:243, InvocableHandlerMethod (org.springframework.web.reactive.result.method)
lambda$invoke$0:138, InvocableHandlerMethod (org.springframework.web.reactive.result.method)
apply:-1, 595198211 (org.springframework.web.reactive.result.method.InvocableHandlerMethod$$Lambda$652)
onNext:118, MonoFlatMap$FlatMapMain (reactor.core.publisher)
complete:1083, Operators$MonoSubscriber (reactor.core.publisher)
signal:247, MonoZip$ZipCoordinator (reactor.core.publisher) .................................................... functional endpoints
findById:24, BookHandler (com.javaworld.webflux.bookservice.web)
handle:-1, 953080701 (com.javaworld.webflux.bookservice.web.BookRouter$$Lambda$437)
handle:61, HandlerFunctionAdapter (org.springframework.web.reactive.function.server.support)
invokeHandler:168, DispatcherHandler (org.springframework.web.reactive)
lambda$handle$1:160, DispatcherHandler (org.springframework.web.reactive)
apply:-1, 1795086753 (org.springframework.web.reactive.DispatcherHandler$$Lambda$550)
onNext:118, MonoFlatMap$FlatMapMain (reactor.core.publisher)
onNext:67, FluxSwitchIfEmpty$SwitchIfEmptySubscriber (reactor.core.publisher)
onNext:76, MonoNext$NextSubscriber (reactor.core.publisher)

参考资料

spring webflux reference

Mastering Spring framework 5, Part 2: Spring WebFlux

Spring boot加载REACTIVE源码分析的更多相关文章

  1. Spring Boot 揭秘与实战 源码分析 - 工作原理剖析

    文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...

  2. Springboot 加载配置文件源码分析

    Springboot 加载配置文件源码分析 本文的分析是基于springboot 2.2.0.RELEASE. 本篇文章的相关源码位置:https://github.com/wbo112/blogde ...

  3. Springboot学习04-默认错误页面加载机制源码分析

    Springboot学习04-默认错误页面加载机制源码分析 前沿 希望通过本文的学习,对错误页面的加载机制有这更神的理解 正文 1-Springboot错误页面展示 2-Springboot默认错误处 ...

  4. ElasticSearch 启动时加载 Analyzer 源码分析

    ElasticSearch 启动时加载 Analyzer 源码分析 本文介绍 ElasticSearch启动时如何创建.加载Analyzer,主要的参考资料是Lucene中关于Analyzer官方文档 ...

  5. Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机

    文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多”开箱即用“的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内 ...

  6. 微服务架构 | *2.3 Spring Cloud 启动及加载配置文件源码分析(以 Nacos 为例)

    目录 前言 1. Spring Cloud 什么时候加载配置文件 2. 准备 Environment 配置环境 2.1 配置 Environment 环境 SpringApplication.prep ...

  7. Spring Cloud Nacos实现动态配置加载的源码分析

    理解了上述Environment的基本原理后,如何从远程服务器上加载配置到Spring的Environment中. NacosPropertySourceLocator 顺着前面的分析思路,我们很自然 ...

  8. springboot Properties加载顺序源码分析

    关于properties: 在spring框架中properties为Environment对象重要组成部分, springboot有如下几种种方式注入(优先级从高到低): 1.命令行 java -j ...

  9. jQuery实现DOM加载方法源码分析

    传统的判断dom加载的方法 使用 dom0级 onload事件来进行触发所有浏览器都支持在最初是很流行的写法 我们都熟悉这种写法: window.onload=function(){ ... }  但 ...

随机推荐

  1. 【python】带图片验证码的登录自动化实战

    近期在跟进新项目的时候,整体的业务线非常之长,会一直重复登录退出不同账号的这个流程,所以想从登录开始实现部分的自动化.因为是B/S的架构,所以采用的是selenium的框架来实现.大致实现步骤如下: ...

  2. [C# 基础知识系列]专题三:如何用委托包装多个方法——委托链 (转载)

    引言: 上一专题介绍了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的介绍都是委托只是封装一个方法,那委托能不能封装多个方法呢?因为生活中经常会听到, ...

  3. 08_java基础知识——方法重载

    一.自变量顺序不同 package com.huawei.test.java04; /** * This is Description * * @author 王明飞 * @date 2018/08/ ...

  4. vue b表单

    你可以用 v-model 指令在表单控件元素上创建双向数据绑定. v-model 会根据控件类型自动选取正确的方法来更新元素. 输入框 实例中演示了 input 和 textarea 元素中使用 v- ...

  5. 卷积神经网络 CNN

    卷积神经网络与普通的神经网络十分相似:他们都由神经元构成,这些神经元拥有可学习的权重和偏差.每一个神经元接收一些输入,执行点积运算并以非线性可选择地跟随它.整个网络仍然表征一个单个可微分的分数函数:从 ...

  6. LeetCode 922. Sort Array By Parity II C++ 解题报告

    922. Sort Array By Parity II 题目描述 Given an array A of non-negative integers, half of the integers in ...

  7. Windows环境下C++中关于文件结束符的问题

    参考资料:http://www.cnblogs.com/day-dayup/p/3572374.html 一.前言 在不同的OS环境下,程序中对应的文件结束符有所不一样,根据<C++ Prime ...

  8. WPF-MVVM-ICommand接口实现

    一 接口分析MVVM框架的目的就是让视图和业务逻辑分离,各干各的.那么怎样实现分离呢,精髓就是绑定ICommand.先看一下ICommand接口的定义: // // 摘要: // 定义一个命令. [T ...

  9. Linux atop监控说明

    2017-02-22 09:42 by pursuer.chen, 7060 阅读, 2 评论, 收藏, 编辑 介绍 atop是一个功能非常强大的linux服务器监控工具,它的数据采集主要包括:CPU ...

  10. 分词工具Hanlp基于感知机的中文分词框架

     结构化感知机标注框架是一套利用感知机做序列标注任务,并且应用到中文分词.词性标注与命名实体识别这三个问题的完整在线学习框架,该框架利用1个算法解决3个问题,时自治同意的系统,同时三个任务顺序渐进,构 ...