SpringBoot中的Reactive编程之NettyReactor

前言

流程

创建IOC容器

先创建IOC容器,ReactiveWebServerApplicationContext。

	context = createApplicationContext();

invokeBeanPostProcessor

ConfigurationClassPostProcessor完成BeanDefinition的载入。

  1. 对应用的@Configuration的解析。【涉及条件过滤@Conditional,只有解析阶段的条件】

  2. 通过this.deferredImportSelectorHandler.process();对SpringBoot的自动配置类的引入跟解析。比如:ReactiveWebServerFactoryAutoConfiguration。

    2.1 在SpringBoot环境中,获取通过grouping.getImports()引入的自动配置类。

    这一阶段包含了从所有的自动配置类 -> 符合条件的自动配置类 ->对符合条件的自动配置类进行排序,以便按照该顺序载入loadBeanDefinitions,这个过程包含了对AutoConfigurationBeforeAutoConfigurationAfterAutoConfigurationOrdered的处理。

    2.2 对每一个自动配置类进行解析处理。【涉及条件过滤@Conditional,只有解析阶段的条件】

  3. 向IOC容器中载入BeanDefinition。【涉及条件过滤@Conditional,只对bean注册的】

onRefresh

通过createWebServer();完成WebServer的创建。

  1. 通过getWebServerFactoryBeanName()获取beanName:nettyReactiveWebServerFactory

  2. 在IOC容器中根据beanName创建bean对象
    注意一点,该beanName所对应的BeanDefinition信息是在invokeBeanPostProcessor阶段完成的。

        @Bean
    	NettyReactiveWebServerFactory nettyReactiveWebServerFactory(ReactorResourceFactory resourceFactory,
    			ObjectProvider<NettyRouteProvider> routes, ObjectProvider<NettyServerCustomizer> serverCustomizers) {
    		NettyReactiveWebServerFactory serverFactory = new NettyReactiveWebServerFactory();
    		serverFactory.setResourceFactory(resourceFactory);
    		routes.orderedStream().forEach(serverFactory::addRouteProviders);
    		serverFactory.getServerCustomizers().addAll(serverCustomizers.orderedStream().collect(Collectors.toList()));
    		return serverFactory;
    	}
    

    通过这种方式声明的Bean,并创建的Bean对象,是通过factoryMethodName创建的。
    在这里插入图片描述
    这个factoryMethodNamefactoryBeanName是怎么来的?

    通过对配置类@Configuration的@Bean的解析和loadBeanDefinitions两个阶段完成。第一阶段的解析是完成配置类中所引入的bean,第二阶段是完成对配置类及其通过该配置类引入的beanDefinition信息的载入。

    这个factoryMethodNamefactoryBeanName分别有什么作用?

    factoryMethodName和factoryBeanName最后都是利用反射执行方法来创建对象的,即:Object result = factoryMethod.invoke(factoryBean, args);
    在这里插入图片描述
    实际执行的方法是:在这里插入图片描述
    如果这种声明@Bean,通过工厂方法创建对象的方式,该方法的参数需要一个集合类型的对象注入怎么办?就比如:nettyReactiveWebServerFactory

    不要用List的形式,直接用ObjectProvider<>的形式。而且,注入时机也是在工厂方法执行的时候。比如:routes.orderedStream().forEach(serverFactory::addRouteProviders);等。
    在这里插入图片描述

  3. nettyReactiveWebServerFactory这个bean对象进行BeanPostProcessor处理,即WebServerFactoryCustomizerBeanPostProcessor在这里插入图片描述

  4. 通过this.beanFactory.getBeansOfType(WebServerFactoryCustomizer.class, false, false)获取WebServerFactoryCustomizer

    4.1 获取一个reactiveWebServerFactoryCustomizer的bean【反射执行】:
    因为需要反射执行工厂方法reactiveWebServerFactoryCustomizer,因此,需要该方法所在的对象即ReactiveWebServerFactoryAutoConfiguration。(该对象会优先创建)

    4.2 获取另一个nettyWebServerFactoryCustomizer的bean

  5. 对NettyReactiveWebServerFactory,用获得的WebServerFactoryCustomizer定制化操作。这个定制化,涉及的是比如yml中定义的相关属性赋值给NettyReactiveWebServerFactory等。

创建完NettyReactiveWebServerFactory后,接下来创建的是WebServerManager。

finishBeanFactoryInitialization

这一阶段完成剩余bean的创建。

  • DefaultCodecsConfiguration
  • defaultCodecCustomizer
  • JacksonCodecConfiguration
  • jacksonCodecCustomizer
  • CodecsAutoConfiguration
  • CodecProperties
  • ErrorWebFluxAutoConfiguration等

finishRefresh

由LifeCycleAutoConfiguration自动配置类创建的DefaultLifecycleProcessor启动。
具体操作的是,getLifecycleProcessor().onRefresh();。(所有的Web服务器,不管是Netty实现,还是Tomcat实现,亦或是Jetty,都是在这一阶段启动的

在这一阶段中,通过getLifecycleBeans()获取生命周期bean,即与Web有关的Server创建:

  • lifecycleProcessor
  • webServerGracefulShutdown
  • webServerStartStop【创建WebServer服务器】,该bean的创建是在ReactiveWebServerApplicationContext中的onRefresh(IOC容器初始化阶段的onRefresh)阶段中。在这里插入图片描述

对获得的每一个Lifecycle进行处理并启动:

	if (!phases.isEmpty()) {
			List<Integer> keys = new ArrayList<>(phases.keySet());
			Collections.sort(keys);
			for (Integer key : keys) {
				// 先启动webServerStartStop = WebServerStartStopLifecycle
				phases.get(key).start();
			}
	}

进入到WebServerStartStopLifecycle:
在这里插入图片描述
WebServerManage启动所做的工作:

  • httpHandler的初始化

    • 获取httpHandler的Bean对象,其bean信息定义是在HttpHandlerAutoConfiguration
    • this.handler.initializeHandler() this.handlerSupplier.get()
    • 这个this.handlerSupplier其实就是在创建WebServerManager时传入的lambda函数:this::getHttpHandler
    • 将获取到的HttpWebHandlerAdapter赋值给WebServerManager的delegate
  • 启动webServer服务器,此处即NettyWebServer

    • 此webServer对象的创建时机:new WebServerManager
    • this.webServer = factory.getWebServer(this.handler);
    • 此factory为NettyReactiveWebServerFactory

    • 启动操作:return server.bindNow();
      Reactor编程:
    public Mono<? extends DisposableServer> bind(TcpServer delegate) {
    		return delegate.bootstrap(this)
    		               .bind()
    		               .map(CLEANUP_GLOBAL_RESOURCE);
    }
    

    这里的bind方法最终是调用TcpServerBind中的bind(ServerBootstrap b)方法。
    实际创建Mono对象也是在此方法中:

    return Mono.create(sink -> {
    			ServerBootstrap bootstrap = b.clone();
    
    			ConnectionObserver obs = BootstrapHandlers.connectionObserver(bootstrap);
    			ConnectionObserver childObs =
    					BootstrapHandlers.childConnectionObserver(bootstrap);
    			ChannelOperations.OnSetup ops =
    					BootstrapHandlers.channelOperationFactory(bootstrap);
    
    			convertLazyLocalAddress(bootstrap);
    
    			BootstrapHandlers.finalizeHandler(bootstrap, ops, new ChildObserver(childObs));
    
    			ChannelFuture f = bootstrap.bind();
    
    			DisposableBind disposableServer = new DisposableBind(sink, f, obs, bootstrap);
    			f.addListener(disposableServer);
    			sink.onCancel(disposableServer);
    		});
    

    在map方法中做的是订阅工作。

    @Nullable
    	public T block(Duration timeout) {
    		// 一个特定功能的CountDownLatch
    		BlockingMonoSubscriber<T> subscriber = new BlockingMonoSubscriber<>();
    		// 订阅,这里会执行Mono.create时的参数函数
    		subscribe((Subscriber<T>) subscriber);
    		// 获取
    		return subscriber.blockingGet(timeout.toMillis(), TimeUnit.MILLISECONDS);
    	}
    

    这也是,官方中为什么说,SpringBoot中提供的Reactive编程是基于Reactor构建的。

HttpServerTcpConfig【层级关系,以防回头再看,从头再理解】

依次向下创建:每次创建本次HttpServerTcpConfig,都把上一次创建的HttpServerTcpConfig传进去。当执行bind(tcpConfiguration())的时候,根据tcpServerMapper.apply(source.tcpConfiguration()执行关于TcpServer的Function。不然,跳过来跳过去,不知做什么。
HttpServerBind - Function【bind】
HttpServerTcpConfig - Function【protocols】
HttpServerTcpConfig - Function【Forward】
HttpServerTcpConfig - Function【请求解码】
HttpServerTcpConfig - Function【channelGroup】
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值