zoukankan      html  css  js  c++  java
  • Spring boot加载REACTIVE源码分析

    一,加载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.classTomcat.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 ControllersFunctional 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

  • 相关阅读:
    如何在markdown隐藏代码块
    html基础
    驻留机制
    字典
    echarts简单使用
    selenium的基本操作
    Excel上传、下载、models 自定义字段、批量执行(可选)
    django之自定义标签(路径url反向解码)
    邮件自动生成发送用例报告
    前台获取后台保存的数据
  • 原文地址:https://www.cnblogs.com/birdstudio/p/9838060.html
Copyright © 2011-2022 走看看