@Override
	public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
		// Get metadata string from http header.
		ServerHttpRequest serverHttpRequest = serverWebExchange.getRequest();

		// transitive metadata
		// from specific header
		Map<String, String> internalTransitiveMetadata = getInternalMetadata(serverHttpRequest, CUSTOM_METADATA);
		// from header with specific prefix
		Map<String, String> customTransitiveMetadata = CustomTransitiveMetadataResolver.resolve(serverWebExchange);
		Map<String, String> mergedTransitiveMetadata = new HashMap<>();
		mergedTransitiveMetadata.putAll(internalTransitiveMetadata);
		mergedTransitiveMetadata.putAll(customTransitiveMetadata);

		// disposable metadata
		// from specific header
		Map<String, String> internalDisposableMetadata = getInternalMetadata(serverHttpRequest, CUSTOM_DISPOSABLE_METADATA);
		Map<String, String> mergedDisposableMetadata = new HashMap<>(internalDisposableMetadata);

		// application metadata
		Map<String, String> internalApplicationMetadata = getInternalMetadata(serverHttpRequest, APPLICATION_METADATA);
		Map<String, String> mergedApplicationMetadata = new HashMap<>(internalApplicationMetadata);

		String callerIp = "";
		if (StringUtils.isNotBlank(mergedApplicationMetadata.get(LOCAL_IP))) {
			callerIp = mergedApplicationMetadata.get(LOCAL_IP);
		}
		// message metadata
		ReactiveMetadataProvider callerMessageMetadataProvider = new ReactiveMetadataProvider(serverHttpRequest, callerIp);

		MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, mergedApplicationMetadata, callerMessageMetadataProvider);

		// Save to ServerWebExchange.
		serverWebExchange.getAttributes().put(
				MetadataConstant.HeaderName.METADATA_CONTEXT,
				MetadataContextHolder.get());

		TransHeadersTransfer.transfer(serverHttpRequest);
		return webFilterChain.filter(serverWebExchange)
				.doOnError(throwable -> LOG.error("handle metadata[{}] error.",
						MetadataContextHolder.get(), throwable))
				.doFinally((type) -> MetadataContextHolder.remove());
	}
@Test
	public void test2() {
		// Create mock WebFilterChain
		WebFilterChain webFilterChain = serverWebExchange -> Mono.empty();

		// Mock request
		MockServerHttpRequest request = MockServerHttpRequest.get("test")
				.header(MetadataConstant.HeaderName.CUSTOM_METADATA, "{\"c\": \"3\"}")
				.build();
		ServerWebExchange exchange = MockServerWebExchange.from(request);

		metadataReactiveFilter.filter(exchange, webFilterChain);
		assertThat(metadataLocalProperties.getContent().get("a")).isEqualTo("1");
		assertThat(metadataLocalProperties.getContent().get("b")).isEqualTo("2");
		assertThat(metadataLocalProperties.getContent().get("c")).isNull();
	}