<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have searched the <a href="https://github.com/apache/incubator-dubbo/issues">issues</a> of this repository and believe that this is not a duplicate.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have checked the <a href="https://github.com/apache/incubator-dubbo/blob/master/FAQ.md">FAQ</a> of this repository and believe that this is not a duplicate.</li>
</ul>
<h2 dir="auto">PROBLEM</h2>
<p dir="auto">Most of the <code class="notranslate">setXxxx</code> and <code class="notranslate">addParameter*</code> in <code class="notranslate">URL</code> such as <code class="notranslate">org.apache.dubbo.common.URL#addParameter</code> and <code class="notranslate">setXxxx</code> will return a new <code class="notranslate">URL</code> object for chaining calls, and most of the <em>"middle objects"</em> are useless and unnecessary, example below:</p>
<blockquote>
<p dir="auto">class <code class="notranslate">org.apache.dubbo.config.spring.SimpleRegistryExporter</code></p>
</blockquote>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="
    public static Exporter&lt;RegistryService&gt; export(int port, RegistryService registryService) {
        return protocol.export(proxyFactory.getInvoker(registryService, RegistryService.class,
                // HERE
                new URL(&quot;dubbo&quot;, NetUtils.getLocalHost(), port, RegistryService.class.getName())
                        .setPath(RegistryService.class.getName()) // useless
                        .addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName()) // useless
                        .addParameter(Constants.CLUSTER_STICKY_KEY, &quot;true&quot;) // useless
                        .addParameter(Constants.CALLBACK_INSTANCES_LIMIT_KEY, &quot;1000&quot;) // useless
                        .addParameter(&quot;ondisconnect&quot;, &quot;disconnect&quot;) // useless
                        .addParameter(&quot;subscribe.1.callback&quot;, &quot;true&quot;) // useless
                        .addParameter(&quot;unsubscribe.1.callback&quot;, &quot;false&quot;)));
    }"><pre class="notranslate">    <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-smi">Exporter</span>&lt;<span class="pl-smi">RegistryService</span>&gt; <span class="pl-s1">export</span>(<span class="pl-smi">int</span> <span class="pl-s1">port</span>, <span class="pl-smi">RegistryService</span> <span class="pl-s1">registryService</span>) {
        <span class="pl-k">return</span> <span class="pl-s1">protocol</span>.<span class="pl-en">export</span>(<span class="pl-s1">proxyFactory</span>.<span class="pl-en">getInvoker</span>(<span class="pl-s1">registryService</span>, <span class="pl-smi">RegistryService</span>.<span class="pl-k">class</span>,
                <span class="pl-c">// HERE</span>
                <span class="pl-k">new</span> <span class="pl-smi">URL</span>(<span class="pl-s">"dubbo"</span>, <span class="pl-smi">NetUtils</span>.<span class="pl-en">getLocalHost</span>(), <span class="pl-s1">port</span>, <span class="pl-smi">RegistryService</span>.<span class="pl-k">class</span>.<span class="pl-en">getName</span>())
                        .<span class="pl-en">setPath</span>(<span class="pl-smi">RegistryService</span>.<span class="pl-k">class</span>.<span class="pl-en">getName</span>()) <span class="pl-c">// useless</span>
                        .<span class="pl-en">addParameter</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">INTERFACE_KEY</span>, <span class="pl-smi">RegistryService</span>.<span class="pl-k">class</span>.<span class="pl-en">getName</span>()) <span class="pl-c">// useless</span>
                        .<span class="pl-en">addParameter</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">CLUSTER_STICKY_KEY</span>, <span class="pl-s">"true"</span>) <span class="pl-c">// useless</span>
                        .<span class="pl-en">addParameter</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">CALLBACK_INSTANCES_LIMIT_KEY</span>, <span class="pl-s">"1000"</span>) <span class="pl-c">// useless</span>
                        .<span class="pl-en">addParameter</span>(<span class="pl-s">"ondisconnect"</span>, <span class="pl-s">"disconnect"</span>) <span class="pl-c">// useless</span>
                        .<span class="pl-en">addParameter</span>(<span class="pl-s">"subscribe.1.callback"</span>, <span class="pl-s">"true"</span>) <span class="pl-c">// useless</span>
                        .<span class="pl-en">addParameter</span>(<span class="pl-s">"unsubscribe.1.callback"</span>, <span class="pl-s">"false"</span>)));
    }</pre></div>
<blockquote>
<p dir="auto">class <code class="notranslate">org.apache.dubbo.config.ServiceConfig</code></p>
</blockquote>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="
    @SuppressWarnings({&quot;unchecked&quot;, &quot;rawtypes&quot;})
    private void exportLocal(URL url) {
        if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
            // HERE
            URL local = URL.valueOf(url.toFullString())
                    .setProtocol(Constants.LOCAL_PROTOCOL) // useless
                    .setHost(LOCALHOST_VALUE) // useless
                    .setPort(0);
            Exporter&lt;?&gt; exporter = protocol.export(
                    proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
            exporters.add(exporter);
            logger.info(&quot;Export dubbo service &quot; + interfaceClass.getName() + &quot; to local registry&quot;);
        }
    }"><pre class="notranslate">    <span class="pl-c1">@</span><span class="pl-c1">SuppressWarnings</span>({<span class="pl-s">"unchecked"</span>, <span class="pl-s">"rawtypes"</span>})
    <span class="pl-k">private</span> <span class="pl-smi">void</span> <span class="pl-s1">exportLocal</span>(<span class="pl-smi">URL</span> <span class="pl-s1">url</span>) {
        <span class="pl-k">if</span> (!<span class="pl-smi">Constants</span>.<span class="pl-c1">LOCAL_PROTOCOL</span>.<span class="pl-en">equalsIgnoreCase</span>(<span class="pl-s1">url</span>.<span class="pl-en">getProtocol</span>())) {
            <span class="pl-c">// HERE</span>
            <span class="pl-smi">URL</span> <span class="pl-s1">local</span> = <span class="pl-smi">URL</span>.<span class="pl-en">valueOf</span>(<span class="pl-s1">url</span>.<span class="pl-en">toFullString</span>())
                    .<span class="pl-en">setProtocol</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">LOCAL_PROTOCOL</span>) <span class="pl-c">// useless</span>
                    .<span class="pl-en">setHost</span>(<span class="pl-c1">LOCALHOST_VALUE</span>) <span class="pl-c">// useless</span>
                    .<span class="pl-en">setPort</span>(<span class="pl-c1">0</span>);
            <span class="pl-smi">Exporter</span>&lt;?&gt; <span class="pl-s1">exporter</span> = <span class="pl-s1">protocol</span>.<span class="pl-en">export</span>(
                    <span class="pl-s1">proxyFactory</span>.<span class="pl-en">getInvoker</span>(<span class="pl-s1">ref</span>, (<span class="pl-smi">Class</span>) <span class="pl-s1">interfaceClass</span>, <span class="pl-s1">local</span>));
            <span class="pl-s1">exporters</span>.<span class="pl-en">add</span>(<span class="pl-s1">exporter</span>);
            <span class="pl-s1">logger</span>.<span class="pl-en">info</span>(<span class="pl-s">"Export dubbo service "</span> + <span class="pl-s1">interfaceClass</span>.<span class="pl-en">getName</span>() + <span class="pl-s">" to local registry"</span>);
        }
    }</pre></div>
<h2 dir="auto">SOLUTION</h2>
<p dir="auto">And I suggest refactoring the <code class="notranslate">URL</code> with <a href="https://en.wikipedia.org/wiki/Builder_pattern" rel="nofollow">Builder Pattern</a>. And the possible usage may be:</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="URL url = ...;
URL newURL = new URLBuilder(url)
.addParameter(k, v)
.addParameter(k2, v2)
.setPath(yourPath)
.build();"><pre class="notranslate"><span class="pl-smi">URL</span> <span class="pl-s1">url</span> = ...;
<span class="pl-smi">URL</span> <span class="pl-s1">newURL</span> = <span class="pl-k">new</span> <span class="pl-smi">URLBuilder</span>(<span class="pl-s1">url</span>)
.<span class="pl-en">addParameter</span>(<span class="pl-s1">k</span>, <span class="pl-s1">v</span>)
.<span class="pl-en">addParameter</span>(<span class="pl-s1">k2</span>, <span class="pl-s1">v2</span>)
.<span class="pl-en">setPath</span>(<span class="pl-s1">yourPath</span>)
.<span class="pl-en">build</span>();</pre></div>
<p dir="auto">Though we cannot remove the original <code class="notranslate">addXXX</code> and <code class="notranslate">setXxxx</code> methods due to compability, we can mark them as deprecated and guide users to use the new <code class="notranslate">URLBuilder</code>.</p>
<blockquote>
<p dir="auto">I'd like to try refactoring this if it's good to the comunity :)</p>
</blockquote>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I have searched the <a href="https://github.com/apache/dubbo/issues">issues</a> of this repository and believe that this is not a duplicate.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I have checked the <a href="https://github.com/apache/dubbo/blob/master/FAQ.md">FAQ</a> of this repository and believe that this is not a duplicate.</li>
</ul>
<h3 dir="auto">Environment</h3>
<ul dir="auto">
<li>Dubbo version: 2.7.1</li>
<li>Operating System version: liunx7</li>
<li>Java version: 1.8</li>
<li>zookeeper version: 3.4.13</li>
</ul>
<h3 dir="auto">Steps to reproduce this issue</h3>
<ol dir="auto">
<li>when I make two service providers : hello.server</li>
<li>then http request the method</li>
<li>then  two service providers all receiverd method  transfer</li>
</ol>
<p dir="auto">Pls. provide [GitHub address] to reproduce this issue.</p>
<h3 dir="auto">Expected Result</h3>
<p dir="auto">What do you expected from the above steps？</p>
<h3 dir="auto">Actual Result</h3>
<p dir="auto">What actually happens?</p>
<p dir="auto">If there is an exception, please attach the exception trace:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Just put your stack trace here!"><pre class="notranslate"><code class="notranslate">Just put your stack trace here!
</code></pre></div>