@Override
    public URL mergeUrl(URL remoteUrl, Map<String, String> localParametersMap) {
        Map<String, String> map = new HashMap<>();
        Map<String, String> remoteMap = remoteUrl.getParameters();

        if (remoteMap != null && remoteMap.size() > 0) {
            map.putAll(remoteMap);

            // Remove configurations from provider, some items should be affected by provider.
            map.remove(THREAD_NAME_KEY);
            map.remove(DEFAULT_KEY_PREFIX + THREAD_NAME_KEY);

            map.remove(THREADPOOL_KEY);
            map.remove(DEFAULT_KEY_PREFIX + THREADPOOL_KEY);

            map.remove(CORE_THREADS_KEY);
            map.remove(DEFAULT_KEY_PREFIX + CORE_THREADS_KEY);

            map.remove(THREADS_KEY);
            map.remove(DEFAULT_KEY_PREFIX + THREADS_KEY);

            map.remove(QUEUES_KEY);
            map.remove(DEFAULT_KEY_PREFIX + QUEUES_KEY);

            map.remove(ALIVE_KEY);
            map.remove(DEFAULT_KEY_PREFIX + ALIVE_KEY);

            map.remove(Constants.TRANSPORTER_KEY);
            map.remove(DEFAULT_KEY_PREFIX + Constants.TRANSPORTER_KEY);
        }

        if (localParametersMap != null && localParametersMap.size() > 0) {
            Map<String, String> copyOfLocalMap = new HashMap<>(localParametersMap);

            if (map.containsKey(GROUP_KEY)) {
                copyOfLocalMap.remove(GROUP_KEY);
            }
            if (map.containsKey(VERSION_KEY)) {
                copyOfLocalMap.remove(VERSION_KEY);
            }
            if (map.containsKey(GENERIC_KEY)) {
                copyOfLocalMap.remove(GENERIC_KEY);
            }

            copyOfLocalMap.remove(RELEASE_KEY);
            copyOfLocalMap.remove(DUBBO_VERSION_KEY);
            copyOfLocalMap.remove(METHODS_KEY);
            copyOfLocalMap.remove(TIMESTAMP_KEY);
            copyOfLocalMap.remove(TAG_KEY);

            map.putAll(copyOfLocalMap);

            if (remoteMap != null) {
                map.put(REMOTE_APPLICATION_KEY, remoteMap.get(APPLICATION_KEY));

                // Combine filters and listeners on Provider and Consumer
                String remoteFilter = remoteMap.get(REFERENCE_FILTER_KEY);
                String localFilter = copyOfLocalMap.get(REFERENCE_FILTER_KEY);
                if (remoteFilter != null
                        && remoteFilter.length() > 0
                        && localFilter != null
                        && localFilter.length() > 0) {
                    map.put(REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter);
                }
                String remoteListener = remoteMap.get(INVOKER_LISTENER_KEY);
                String localListener = copyOfLocalMap.get(INVOKER_LISTENER_KEY);
                if (remoteListener != null
                        && remoteListener.length() > 0
                        && localListener != null
                        && localListener.length() > 0) {
                    map.put(INVOKER_LISTENER_KEY, remoteListener + "," + localListener);
                }
            }
        }

        return remoteUrl.clearParameters().addParameters(map);
    }
@Test
    void testMergeUrl() {
        URL providerURL = URL.valueOf("dubbo://localhost:55555");
        providerURL = providerURL.setPath("path").setUsername("username").setPassword("password");

        providerURL = URLBuilder.from(providerURL)
                .addParameter(GROUP_KEY, "dubbo")
                .addParameter(VERSION_KEY, "1.2.3")
                .addParameter(DUBBO_VERSION_KEY, "2.3.7")
                .addParameter(THREADPOOL_KEY, "fixed")
                .addParameter(THREADS_KEY, Integer.MAX_VALUE)
                .addParameter(THREAD_NAME_KEY, "test")
                .addParameter(CORE_THREADS_KEY, Integer.MAX_VALUE)
                .addParameter(QUEUES_KEY, Integer.MAX_VALUE)
                .addParameter(ALIVE_KEY, Integer.MAX_VALUE)
                .addParameter(DEFAULT_KEY_PREFIX + THREADS_KEY, Integer.MAX_VALUE)
                .addParameter(DEFAULT_KEY_PREFIX + THREADPOOL_KEY, "fixed")
                .addParameter(DEFAULT_KEY_PREFIX + CORE_THREADS_KEY, Integer.MAX_VALUE)
                .addParameter(DEFAULT_KEY_PREFIX + QUEUES_KEY, Integer.MAX_VALUE)
                .addParameter(DEFAULT_KEY_PREFIX + ALIVE_KEY, Integer.MAX_VALUE)
                .addParameter(DEFAULT_KEY_PREFIX + THREAD_NAME_KEY, "test")
                .addParameter(APPLICATION_KEY, "provider")
                .addParameter(REFERENCE_FILTER_KEY, "filter1,filter2")
                .addParameter(TAG_KEY, "TTT")
                .build();

        URL consumerURL = new URLBuilder(DUBBO_PROTOCOL, "localhost", 55555)
                .addParameter(PID_KEY, "1234")
                .addParameter(THREADPOOL_KEY, "foo")
                .addParameter(APPLICATION_KEY, "consumer")
                .addParameter(REFERENCE_FILTER_KEY, "filter3")
                .addParameter(TAG_KEY, "UUU")
                .build();

        URL url = providerURLMergeProcessor.mergeUrl(providerURL, consumerURL.getParameters());

        Assertions.assertFalse(url.hasParameter(THREADS_KEY));
        Assertions.assertFalse(url.hasParameter(DEFAULT_KEY_PREFIX + THREADS_KEY));

        Assertions.assertFalse(url.hasParameter(DEFAULT_KEY_PREFIX + THREADPOOL_KEY));

        Assertions.assertFalse(url.hasParameter(CORE_THREADS_KEY));
        Assertions.assertFalse(url.hasParameter(DEFAULT_KEY_PREFIX + CORE_THREADS_KEY));

        Assertions.assertFalse(url.hasParameter(QUEUES_KEY));
        Assertions.assertFalse(url.hasParameter(DEFAULT_KEY_PREFIX + QUEUES_KEY));

        Assertions.assertFalse(url.hasParameter(ALIVE_KEY));
        Assertions.assertFalse(url.hasParameter(DEFAULT_KEY_PREFIX + ALIVE_KEY));

        Assertions.assertFalse(url.hasParameter(THREAD_NAME_KEY));
        Assertions.assertFalse(url.hasParameter(DEFAULT_KEY_PREFIX + THREAD_NAME_KEY));

        Assertions.assertEquals("path", url.getPath());
        Assertions.assertEquals("username", url.getUsername());
        Assertions.assertEquals("password", url.getPassword());
        Assertions.assertEquals("1234", url.getParameter(PID_KEY));
        Assertions.assertEquals("foo", url.getParameter(THREADPOOL_KEY));
        Assertions.assertEquals("consumer", url.getApplication());
        Assertions.assertEquals("provider", url.getRemoteApplication());
        Assertions.assertEquals("filter1,filter2,filter3", url.getParameter(REFERENCE_FILTER_KEY));

        Assertions.assertEquals("TTT", url.getParameter(TAG_KEY));
    }