学习目标

  1. 理解WebFlux核心组件HttpHandler、WebHandler的创建过程
  2. 理解DispatcherHandler如何映射请求url及参数的过程
  3. 理解Netty服务的主要启动节点

此次学习的Spring boot版本为2.6.6,对应的Spring webflux版本为5.3.18

入口

Springboot工程入口方法为 SpringApplication.run() ,从此方法开始进行分析。

1
2
3
public static void main(String[] args) {
    SpringApplication.run(Main.class, args);
}

决定启动的web应用类型

整个服务的web应用类型是在构造 SpringApplication 类时进行确定的,具体代码如下:

1
this.webApplicationType = WebApplicationType.deduceFromClasspath();

判断应用类型的逻辑

  1. org.springframework.web.reactive.DispatcherHandler存在
  2. org.springframework.web.servlet.DispatcherServlet不存在
  3. org.glassfish.jersey.servlet.ServletContainer不存在

即确认webApplicationType为 Reactive

1
2
3
4
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
    && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
    return WebApplicationType.REACTIVE;
}

创建具体的ApplicationContext

根据webApplicationType(Reactive)确定创建的ApplicationContext为AnnotationConfigReactiveWebServerApplicationContext,此Context支持 @ComponentJSR-330规范中 @Inject 形式的依赖注解

1
SpringAplication.createApplicationContext()
1
2
3
4
5
6
7
8
switch (webApplicationType) {
case SERVLET:
    return new AnnotationConfigServletWebServerApplicationContext();
case REACTIVE:
    return new AnnotationConfigReactiveWebServerApplicationContext();
default:
    return new AnnotationConfigApplicationContext();
}

最主要的ApplicationContext.refresh()方法

refresh的Refresh阶段

刷新操作是在 AbstractApplicationContext 类的refresh方法中进行,在调用invokeBeanFactoryPostProcessors方法时会有对controller注解的扫描与处理

扫描Controller注解

ConfigurationClassPostProcessor.processConfigBeanDefinitions() 对Bean定义进行处理,此次研究只关注controller的处理, 具体的处理逻辑在 AbstractHandlerMethodMapping.initHandlerMethods() 方法中,最终调用的是 detectHandlerMethods() 方法,后续进行Handler方法的注册

1
2
3
if (beanType != null && isHandler(beanType)) {
    detectHandlerMethods(beanName);
}
  • Controller方法支持的条件

    1. patternsCondition
    2. methodsCondition
    3. paramsCondition
    4. headersCondition
    5. consumesCondition
    6. producesCondition
    7. customConditionHolder
  • 注册Handler方法

    AbstractHandlerMethodMapping调用MappingRegistry.register()进行Handler注册

    1
    2
    3
    4
    5
    
    private final MappingRegistry mappingRegistry = new MappingRegistry();
    
    protected void registerHandlerMethod(Object handler, Method method, T mapping) {
        this.mappingRegistry.register(mapping, handler, method);
    }
    

refresh的onRefresh阶段

createWebServer

在onRefresh阶段, AnnotationConfigReactiveWebServerApplicationContext的父类ReactiveWebServerApplicationContext进行了webServer的创建

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@Override
protected void onRefresh() {
    super.onRefresh();
    try {
        createWebServer();
    }
    catch (Throwable ex) {
        throw new ApplicationContextException("Unable to start reactive web server", ex);
    }
}
  1. 创建webServer具体由WebServerManager类处理,WebServerManager中创建的httpHandler是Delayed,也就是延迟初始化的
  • 获取BeanFactory

    1
    
    ReactiveWebServerFactory webServerFactory = getWebServerFactory(webServerFactoryBeanName);
    

    获取到的Factory为 NettyReactiveWebServerFactory

  • 创建HttpServer

    主要逻辑在NettyReactiveWebServerFactory->getWebServer()方法中,在createHttpServer中看到了 HttpServer server = HttpServer.create();

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    
    @Override
    public WebServer getWebServer(HttpHandler httpHandler) {
        HttpServer httpServer = createHttpServer();
        ReactorHttpHandlerAdapter handlerAdapter = new ReactorHttpHandlerAdapter(httpHandler);
        NettyWebServer webServer = createNettyWebServer(httpServer, handlerAdapter, this.lifecycleTimeout,
                                                        getShutdown());
        webServer.setRouteProviders(this.routeProviders);
        return webServer;
    }
    
    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.runOn(resources).bindAddress(this::getListenAddress);
        }
        else {
            server = server.bindAddress(this::getListenAddress);
        }
        if (getSsl() != null && getSsl().isEnabled()) {
            server = customizeSslConfiguration(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);
    }
    

refresh的finishBeanFactoryInitialization阶段

设置DispatcherHandler

初始化WebHandler,也就是DispatcherHandler,因为DispatcherHandler实现了ApplicationContextAware接口,在加载Spring配置时,setApplicationContext方法会被调用,setApplicationContext主要做了统一分发策略的处理

  1. SimpleUrlHandlerMapping主要使用的handleMapping
  2. handlerAdapters
  3. resultHandlers

构建HttpHandler

HttpHandlerAutoConfiguration自动装配,调用WebHttpHandlerBuilder.applicationContext(this.applicationContext).build()构建真正的 HttpHandler

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@Bean
public HttpHandler httpHandler(ObjectProvider<WebFluxProperties> propsProvider) {
    HttpHandler httpHandler = WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();
    WebFluxProperties properties = propsProvider.getIfAvailable();
    if (properties != null && StringUtils.hasText(properties.getBasePath())) {
        Map<String, HttpHandler> handlersMap = Collections.singletonMap(properties.getBasePath(), httpHandler);
        return new ContextPathCompositeHandler(handlersMap);
    }
    return httpHandler;
}
  • WebHttpHandlerBuilder.applicationContext()

    Builder的通过context进行HttpHandler字段信息构建,主要包含以下字段信息

    1. webFilters 服务使用的过滤器
    2. exceptionHandlers 异常处理器
    3. sessionManager 会话管理器
    4. codecConfigurer 编解码配置
  • FilterChain的构建

    WebHttpHandlerBuilder.build() 方法调用 new FilteringWebHandler方法进行DefaultWebFilterChain的创建,构建的FilterChain主要是用来对请求Filter的链式操作

    1
    2
    3
    4
    
    public FilteringWebHandler(WebHandler handler, List<WebFilter> filters) {
        super(handler);
        this.chain = new DefaultWebFilterChain(handler, filters);
    }
    

refresh的finishRefresh阶段

启动Server

终于看到服务的启动了,在调用链路 finishRefresh->getLifecycleProcessor().onRefresh()->DefaultLifecycleProcessor.startBeans()->doStart()

  1. initializeHandler初始化Handler为 HttpWebHandlerAdapter(WebHandler到HttpHandler的适配器)
  2. NettyWebServer.startHttpServer()
1
2
3
4
5
@Override
public void start() {
    this.weServerManager.start();
    this.running = true;
}
  • HttpWebHandlerAdapter

    至此,服务准备就绪。