blob: 807e023dd0604574936f10b3220850c718c1bbba [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<title>Developer Guide-zh - Dubbo - Alibaba Open Sesame</title>
<meta http-equiv="X-UA-Compatible" content="IE=8">
<meta charset="UTF-8">
<!-- Deprecated since 3.4. To be removed in a future version of Confluence; use AJS.Confluence.getContextPath() -->
<meta id="confluence-context-path" name="confluence-context-path" content="/wiki">
<meta name="ajs-context-path" content="/wiki">
<meta name="ajs-version-number" content="3.5.9">
<meta name="ajs-build-number" content="2166">
<meta id="atlassian-token" name="atlassian-token" content="c116db80711201b36e2067aa83f3b044c2d5a30e">
<meta id="confluence-space-key" name="confluence-space-key" content="dubbo">
<meta name="ajs-remote-user" content="">
<meta name="ajs-static-resource-url-prefix" content="/wiki/s/en/2166/34/_">
<script type="text/javascript">
// Deprecated global variables. To be removed in a future version of Confluence.
var contextPath = '/wiki';
</script>
<!-- include system css resources -->
<link type="text/css" rel="stylesheet" href="batch.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/26/_/download/superbatch/css/batch.css" media="all">
<!--[if IE]>
<link type="text/css" rel="stylesheet" href="batch.css-ieonly=true.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/26/_/download/superbatch/css/batch.css?ieonly=true" media="all">
<![endif]-->
<link type="text/css" rel="stylesheet" href="batch.css-media=print.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/26/_/download/superbatch/css/batch.css?media=print" media="print">
<link type="text/css" rel="stylesheet" href="com.atlassian.confluence.ext.newcode-macro-plugin-syntaxhighlighter.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.9.10/_/download/batch/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter.css" media="all">
<link type="text/css" rel="stylesheet" href="com.atlassian.confluence.ext.newcode-macro-plugin-sh-theme-confluence.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.9.10/_/download/batch/com.atlassian.confluence.ext.newcode-macro-plugin:sh-theme-confluence/com.atlassian.confluence.ext.newcode-macro-plugin:sh-theme-confluence.css" media="all">
<link type="text/css" rel="stylesheet" href="confluence-forms.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0/_/download/resources/confluence.web.resources:aui-forms/confluence-forms.css" media="all">
<!--[if IE]>
<link type="text/css" rel="stylesheet" href="confluence.web.resources-aui-forms.css-ieonly=true.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0/_/download/batch/confluence.web.resources:aui-forms/confluence.web.resources:aui-forms.css?ieonly=true" media="all">
<![endif]-->
<link type="text/css" rel="stylesheet" href="com.atlassian.confluence.plugins.share-page-mail-page-resources.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.8/_/download/batch/com.atlassian.confluence.plugins.share-page:mail-page-resources/com.atlassian.confluence.plugins.share-page:mail-page-resources.css" media="all">
<link type="text/css" rel="stylesheet" href="confluence.web.resources-view-comment.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0/_/download/batch/confluence.web.resources:view-comment/confluence.web.resources:view-comment.css" media="all">
<!--[if IE]>
<link type="text/css" rel="stylesheet" href="confluence.web.resources-view-comment.css-ieonly=true.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0/_/download/batch/confluence.web.resources:view-comment/confluence.web.resources:view-comment.css?ieonly=true" media="all">
<![endif]-->
<link type="text/css" rel="stylesheet" href="confluence.macros.advanced-fancy-box.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.16/_/download/batch/confluence.macros.advanced:fancy-box/confluence.macros.advanced:fancy-box.css" media="all">
<link type="text/css" rel="stylesheet" href="com.atlassian.confluence.plugins.drag-and-drop-support.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0.16/_/download/batch/com.atlassian.confluence.plugins.drag-and-drop:support/com.atlassian.confluence.plugins.drag-and-drop:support.css" media="all">
<link type="text/css" rel="stylesheet" href="com.atlassian.plugins.shortcuts.atlassian-shortcuts-module-shortcuts.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/0.8/_/download/batch/com.atlassian.plugins.shortcuts.atlassian-shortcuts-module:shortcuts/com.atlassian.plugins.shortcuts.atlassian-shortcuts-module:shortcuts.css" media="all">
<link type="text/css" rel="stylesheet" href="com.atlassian.confluence.keyboardshortcuts-confluence-keyboard-shortcuts.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/3.5.9/_/download/batch/com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts/com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts.css" media="all">
<!-- end system css resources -->
<link rel="stylesheet" href="combined.css-spaceKey=dubbo.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/3/_/styles/combined.css?spaceKey=dubbo" type="text/css">
<meta name="confluence-request-time" content="1392025461398">
<meta name="loggedInUsername" content="">
<meta name="ajs-keyboardshortcut-hash" content="bf02a79603372a43d395a0a429bdf66">
<!-- Deprecated since 3.4. To be removed in a future version of Confluence; use atl.header -->
<script type="text/x-template" title="share-content-popup">
<form action="#" method="post" class="aui share-content-popup">
<fieldset>
<label for="users">User name or email</label>
<div class="autocomplete-user-target">
<input class="text autocomplete-sharepage" id="users" data-max="10" data-dropdown-target=".autocomplete-user-target" data-none-message="No matching user or email found"/>
</div>
<ol class="recipients">
</ol>
<div><label for="note">Note</label></div>
<textarea class="textarea" id="note" placeholder="Add an optional note"/>
</fieldset>
<div class="button-panel">
<div class="progress-messages-icon"></div>
<div class="progress-messages">
</div>
<input class="button submit" type="submit" value="Share" disabled/>
<a class="close-dialog" href="#">Cancel</a>
</div>
</form>
</script>
<script type="text/x-template" title="share-content-popup-recipient-username">
<li data-username="{username}" style="display: none">
<span>
<img src="{thumbnailLink.href}" title="{title}">
<span>{title}</span>
<span class="remove-recipient"/>
</span>
</li>
</script>
<script type="text/x-template" title="share-content-popup-recipient-email">
<li data-email="{email}" style="display: none">
<span>
<img src="{icon}" title="{email}">
<span>{email}</span>
<span class="remove-recipient"/>
</span>
</li>
</script>
<meta name="ajs-use-keyboard-shortcuts" content="true">
<link rel="shortcut icon" href="/wiki/favicon.ico">
<link rel="icon" type="image/png" href="/wiki/s/en/2166/34/_/images/logo/confluence_16.png">
<link rel="search" type="application/opensearchdescription+xml" href="/wiki/opensearch/osd.action" title="Alibaba Open Sesame"/>
<!-- include system javascript resources -->
<script type="text/javascript" src="batch.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/26/_/download/superbatch/js/batch.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.ext.newcode-macro-plugin-syntaxhighlighter.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.9.10/_/download/batch/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.ext.newcode-macro-plugin-syntaxhighlighter-brushes.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.9.10/_/download/batch/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter-brushes/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter-brushes.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.plugins.share-page-mail-page-resources.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.8/_/download/batch/com.atlassian.confluence.plugins.share-page:mail-page-resources/com.atlassian.confluence.plugins.share-page:mail-page-resources.js" ></script>
<script type="text/javascript" src="confluence.macros.advanced-fancy-box.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.16/_/download/batch/confluence.macros.advanced:fancy-box/confluence.macros.advanced:fancy-box.js" ></script>
<script type="text/javascript" src="confluence.macros.advanced-thumbnail-images.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.16/_/download/batch/confluence.macros.advanced:thumbnail-images/confluence.macros.advanced:thumbnail-images.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.plugins.drag-and-drop-support.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0.16/_/download/batch/com.atlassian.confluence.plugins.drag-and-drop:support/com.atlassian.confluence.plugins.drag-and-drop:support.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.plugins.drag-and-drop-drag-and-drop-for-view-content.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0.16/_/download/batch/com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-view-content/com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-view-content.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.plugins.doctheme-splitter.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.9/_/download/batch/com.atlassian.confluence.plugins.doctheme:splitter/com.atlassian.confluence.plugins.doctheme:splitter.js" ></script>
<script type="text/javascript" src="com.atlassian.plugins.shortcuts.atlassian-shortcuts-module-shortcuts.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/0.8/_/download/batch/com.atlassian.plugins.shortcuts.atlassian-shortcuts-module:shortcuts/com.atlassian.plugins.shortcuts.atlassian-shortcuts-module:shortcuts.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.keyboardshortcuts-confluence-keyboard-shortcuts.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/3.5.9/_/download/batch/com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts/com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts.js" ></script>
<script type="text/javascript" src="legacy.confluence.web.resources-prototype.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0/_/download/batch/legacy.confluence.web.resources:prototype/legacy.confluence.web.resources:prototype.js" ></script>
<!-- end system javascript resources -->
<link rel="canonical" href="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh">
<link rel="shortlink" href="http://code.alibabatech.com/wiki/x/zwdq">
<meta name="wikilink" content="[dubbo:Developer Guide-zh]">
<meta name="page-version" content="110">
</head>
<body onload="placeFocus()"
id="com-atlassian-confluence" class="theme-default ">
<ul id="assistive-skip-links" class="assistive">
<li><a href="#title-heading">Skip to content</a></li>
<li><a href="#breadcrumbs">Skip to breadcrumbs</a></li>
<li><a href="#header-menu-bar">Skip to header menu</a></li>
<li><a href="#navigation">Skip to action menu</a></li>
<li><a href="#quick-search-query">Skip to quick search</a></li>
</ul>
<div id="page">
<div id="full-height-container">
<fieldset class="hidden parameters">
<input type="hidden" id="shortcutDialogTip" value="Shortcut tip: Pressing <b>{shortcut}</b> also opens this dialog box">
<input type="hidden" title="i18n.close.name" value="Close">
<input type="hidden" title="i18n.cancel.name" value="Cancel">
</fieldset><fieldset class="hidden parameters">
<input type="hidden" id="statusDialogHeading" value="What are you working on?">
<input type="hidden" id="statusDialogAccessibilityLabel" value="Enter your status (140 character limit)">
<input type="hidden" id="statusDialogLatestLabel" value="Last update:">
<input type="hidden" id="statusDialogUpdateButtonLabel" value="Update">
<input type="hidden" id="statusDialogCancelButtonLabel" value="Cancel">
</fieldset>
<fieldset class="hidden parameters">
<input type="hidden" id="globalSettingsAttachmentMaxSize" value="10485760">
<input type="hidden" id="userLocale" value="en_GB">
<input type="hidden" id="staticResourceUrlPrefix" value="/wiki/s/en/2166/34/_">
<input type="hidden" id="contextPath" value="/wiki">
</fieldset>
<div id="header" class="" style="display: none">
<form id="quick-search" class="quick-search" method="get" action="http://10.20.160.198/wiki/dosearchsite.action">
<fieldset>
<label class="assistive" for="quick-search-query">Quick Search</label>
<input class="quick-search-query" id="quick-search-query" type="text" accessKey="q" autocomplete="off" name="queryString" size="25" title="Quick Search" />
<input class="quick-search-submit" id="quick-search-submit" type="submit" value="Search" />
<div class="aui-dd-parent quick-nav-drop-down"><!-- Quick nav appears here --></div>
</fieldset>
<fieldset class="hidden parameters">
<input type="hidden" id="quickNavEnabled" value="true" />
</fieldset>
</form>
<ul id="header-menu-bar" class="ajs-menu-bar">
<li class="normal ajs-menu-item">
<a id="browse-menu-link" class="browse trigger ajs-menu-title" href="#"><span><span>Browse</span></span></a> <div class="assistive ajs-drop-down">
<ul id="browse-menu-link-leading" class="section-leading first">
<li>
<a id="space-pages-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/listpages.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/listpages.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/pages/listpages.action?key=dubbo" class="" title="Browse pages in the Dubbo space">
<span>Pages</span></a> </li>
<li>
<a id="space-blogposts-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewrecentblogposts.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewrecentblogposts.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/pages/viewrecentblogposts.action?key=dubbo" class="" title="Browse blogs in the Dubbo space">
<span>Blog</span></a> </li>
<li>
<a id="space-labels-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/labels/listlabels-heatmap.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/labels/listlabels-heatmap.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/labels/listlabels-heatmap.action?key=dubbo" class="" title="Browse labels in the Dubbo space">
<span>Labels</span></a> </li>
<li>
<a id="space-attachments-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/spaces/listattachmentsforspace.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/spaces/listattachmentsforspace.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/spaces/listattachmentsforspace.action?key=dubbo" class="" title="Browse attachments in the Dubbo space">
<span>Attachments</span></a> </li>
<li>
<a id="space-mail-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/spaces/viewmailarchive.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/spaces/viewmailarchive.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/spaces/viewmailarchive.action?key=dubbo" class="" title="Browse mail in the Dubbo space">
<span>Mail</span></a> </li>
<li>
<a id="space-advanced-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/spaces/viewspacesummary.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/spaces/viewspacesummary.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/spaces/viewspacesummary.action?key=dubbo" class="" title="Browse additional space functions in the Dubbo space">
<span>Advanced</span></a> </li>
<li>
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/spaces/usage/report.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/spaces/usage/report.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/spaces/usage/report.action?key=dubbo" class="" title="">
<span>Activity</span></a> </li>
</ul>
<ul id="browse-menu-link-global" class="section-global">
<li>
<a id="whats-new-menu-link" href="javascript:if(confirm(%27http://docs.atlassian.com/confluence/docs-35/whatsnew/iframe \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://docs.atlassian.com/confluence/docs-35/whatsnew/iframe%27" tppabs="http://docs.atlassian.com/confluence/docs-35/whatsnew/iframe" class="" title="">
<span>What’s New</span></a> </li>
<li>
<a id="people-directory-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/peopledirectory.action \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/peopledirectory.action%27" tppabs="http://10.20.160.198/wiki/peopledirectory.action" class="" title="Browse the Confluence people directory">
<span>People Directory</span></a> </li>
<li>
<a id="space-directory-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/spacedirectory/view.action \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/spacedirectory/view.action%27" tppabs="http://10.20.160.198/wiki/spacedirectory/view.action" class="" title="Browse the Confluence space directory">
<span>Space Directory</span></a> </li>
<li>
<a id="keyboard-shortcuts-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki%27" tppabs="http://10.20.160.198/wiki" class="" title="View available keyboard shortcuts">
<span>Keyboard Shortcuts</span></a> </li>
<li>
<a id="gadget-directory-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki%27" tppabs="http://10.20.160.198/wiki" class="user-item administration-link" title="Browse gadgets provided by Confluence">
<span>Confluence Gadgets</span></a> </li>
</ul>
</div>
</li>
<li class="ajs-menu-item normal">
<a id="login-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/login.action?os_destination=%2Fdisplay%2Fdubbo%2FDeveloper%2BGuide-zh%3FfocusedCommentId%3D8781873 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/login.action?os_destination=%2Fdisplay%2Fdubbo%2FDeveloper%2BGuide-zh%3FfocusedCommentId%3D8781873%27" tppabs="http://10.20.160.198/wiki/login.action?os_destination=%2Fdisplay%2Fdubbo%2FDeveloper%2BGuide-zh%3FfocusedCommentId%3D8781873" class="user-item login-link" title="">
<span>Log In</span></a> </li>
</ul>
<ol id="breadcrumbs">
<li class="first" >
<span><a href="javascript:if(confirm(%27http://10.20.160.198/wiki/dashboard.action \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/dashboard.action%27" tppabs="http://10.20.160.198/wiki/dashboard.action" title="Go to Dashboard">Dashboard</a></span>
</li>
<li>
<span><a href="javascript:if(confirm(%27http://10.20.160.198/wiki/display/dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/display/dubbo%27" tppabs="http://10.20.160.198/wiki/display/dubbo">Dubbo</a></span>
</li>
<li>
<span><a href="Home-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Home-zh">Home-zh</a></span>
</li>
<li>
<span>Developer Guide-zh</span>
</li>
</ol>
</div><!-- \#header -->
<div id="main" >
<div id="navigation" class="content-navigation view" style="display: none">
<fieldset class="hidden parameters">
<input type="hidden" id="pageId" value="6948815">
</fieldset>
<ul class="ajs-menu-bar">
<li class="normal ajs-menu-item">
<a id="add-menu-link" class="add trigger ajs-menu-title" href="#"><span><span>Add</span></span></a> <div class="assistive ajs-drop-down">
<ul id="add-menu-link-page" class="section-page first">
<li>
<a id="add-comment-menu-link" href="Developer+Guide-zh-showComments=true&showCommentArea=true.htm#addcomment" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?showComments=true&showCommentArea=true#addcomment" class="add-comment" title="Add a Comment">
<span>Comment</span></a> </li>
</ul>
</div>
</li>
<li class="normal ajs-menu-item">
<a id="action-menu-link" class="action trigger ajs-menu-title" href="#"><span><span>Tools</span></span></a> <div class="assistive ajs-drop-down">
<ul id="action-menu-link-primary" class="section-primary first">
<li>
<a id="view-attachments-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewpageattachments.action?pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewpageattachments.action?pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/viewpageattachments.action?pageId=6948815" class="action-view-attachments" accessKey="a" title="View Attachments">
<span><u>A</u>ttachments (0)</span></a> </li>
<li>
<a id="action-view-history-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewpreviousversions.action?pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewpreviousversions.action?pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/viewpreviousversions.action?pageId=6948815" class="action-view-history" title="">
<span>Page History</span></a> </li>
<li>
<a id="action-page-permissions-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6948815" class="action-page-permissions" title="Edit restrictions">
<span>Restrictions</span></a> </li>
</ul>
<ul id="action-menu-link-secondary" class="section-secondary">
<li>
<a id="view-page-info-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6948815" class="action-view-info" title="">
<span>Info</span></a> </li>
<li>
<a id="link-to-page-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6948815" class="" title="Link to this Page">
<span>Link to this Page&hellip;</span></a> </li>
<li>
<a id="view-in-hierarchy-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/listpages-dirview.action?key=dubbo&openId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/listpages-dirview.action?key=dubbo&openId=6948815#selectedPageInHierarchy%27" tppabs="http://10.20.160.198/wiki/pages/listpages-dirview.action?key=dubbo&openId=6948815#selectedPageInHierarchy" class="" title="">
<span>View in Hierarchy</span></a> </li>
<li>
<a id="action-view-source-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewpagesrc.action?pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewpagesrc.action?pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/viewpagesrc.action?pageId=6948815" class="action-view-source popup-link" title="">
<span>View Wiki Markup</span></a> </li>
</ul>
</div>
</li>
</ul>
</div>
<h1 id="title-heading" class="pagetitle" style="display: none">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/display/dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/display/dubbo%27" tppabs="http://10.20.160.198/wiki/display/dubbo"><img class="logo space custom" src="dubbo-version=5&modificationDate=1320723683000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6324241/dubbo?version=5&modificationDate=1320723683000" alt=""></a>
</h1>
<div id="content" class="page view">
<div id="link-to-page-fields" class="hidden parameters">
<input type="hidden" id="linkToThisPageHeading" value="Link to this Page">
<input type="hidden" id="linkToThisPageLink" value="Link">
<input type="hidden" id="linkToThisPageTinyLink" value="Tiny Link">
<input type="hidden" id="linkToThisPageWikiMarkup" value="Wiki Markup">
<input type="hidden" id="linkToThisPageClose" value="Close">
</div>
<fieldset class="hidden parameters">
<input type="hidden" title="movePageDialogViewPageTitle" value="Move Page &ndash; &#8216;Developer Guide-zh&#8217;">
<input type="hidden" title="movePageDialogEditPageTitle" value="Set Page Location">
<input type="hidden" title="movePageDialogMoveButton" value="Move">
<input type="hidden" title="movePageDialogCancelButton" value="Cancel">
<input type="hidden" title="movePageDialogBrowsePanelTip" value="Click to select the new parent page for this page and its children.">
<input type="hidden" title="movePageDialogSearchPanel" value="Search">
<input type="hidden" title="movePageDialogHistoryPanel" value="Recently Viewed">
<input type="hidden" title="movePageDialogHistoryNoResults" value="There were no recently viewed pages found.">
<input type="hidden" title="movePageDialogLocationPanel" value="Known Location">
<input type="hidden" title="movePageDialogLocationNotFound" value="The specified page was not found.">
<input type="hidden" title="movePageDialogBrowsePanel" value="Browse">
<input type="hidden" title="movePageDialogPanelLoadErrorMsg" value="Error reading the panel content from the server.">
<input type="hidden" title="movePageDialogPanelLoadErrorTip" value="You could try reloading the page and launching the dialog again.">
<input type="hidden" title="movePageDialogPanelLoadErrorStatus" value="HTTP Status">
<input type="hidden" title="movePageDialogNoSelectionErrorMsg" value="You must make a selection in the tree before you can move the page.">
<input type="hidden" title="movePageDialogSearchError" value="Failed to retrieve search results from the server.">
<input type="hidden" title="movePageDialogSearchNoResults" value="There were no pages found containing <b>{0}</b>.">
<input type="hidden" title="movePageDialogSearchResultCount" value="Showing <b>{0}</b>-<b>{1}</b> of <b>{2}</b> pages containing <b>{3}</b>.">
<input type="hidden" title="movePageDialogMoveFailed" value="Move failed. There was a problem contacting the server.">
<input type="hidden" title="movePageDialogCannotChangeSpace" value="You cannot move this page to another space because you do not have permission to remove it from this space.">
<input type="hidden" title="pageTitle" value="Developer Guide-zh"/>
<input type="hidden" title="parentPageTitle" value="Home-zh"/>
<input type="hidden" title="fromPageTitle" value=""/>
<input type="hidden" title="spaceKey" value="dubbo"/>
<input type="hidden" title="spaceName" value="Dubbo"/>
<input type="hidden" title="movePageDialogInvalidLocation" value="You cannot move a page to be underneath itself or its children."/>
<input type="hidden" title="movePageDialogOrderingTitle" value="Page Ordering"/>
<input type="hidden" title="movePageDialogBackButton" value="Back"/>
<input type="hidden" title="movePageDialogMoveAndOrderButton" value="Reorder"/>
<input type="hidden" title="movePageDialogNextButton" value="Move"/>
</fieldset>
<script type="text/x-template" title="movePageDialog">
<div class="row information">
<div class="inner">
<div class="element">
Specify the new parent page for this page and its children by space and title.
</div>
</div>
</div>
<div class="form">
<fieldset>
<legend class="assistive"><span>Change the Parent Page to a Known Page</span></legend>
<div class="row">
<label for="new-space">New space:</label>
<div class="value new-space-value">
<input id="new-space-key" name="new-space-key" type="hidden" value="dubbo">
<span class="space-input">
<input id="new-space" name="new-space" value="Dubbo" disabled="disabled">
</span>
<span class="description warning">You cannot move this page to another space because you do not have permission to remove it from this space.</span>
<div class="new-space-dropdown aui-dd-parent autocomplete"></div>
</div>
</div>
<div class="row">
<label for="new-parent-page">New parent page:</label>
<div class="value new-parent-page-value">
<span class="page-input">
<input id="new-parent-page" name="new-parent-page" value="Home-zh">
</span>
<span class="description">Start typing a page title to see a list of suggestions.</span>
<div class="new-parent-page-dropdown aui-dd-parent autocomplete"></div>
</div>
</div>
</fieldset>
</div>
<div class="location-info">
<div class="row">
<label>Current location:</label>
<div class="value breadcrumbs-container">
<div class="breadcrumbs-line">
<ul id="current-parent-breadcrumbs" class="breadcrumbs">
</ul>
</div>
</div>
</div>
<div class="row">
<label>New location:</label>
<div class="value breadcrumbs-container">
<div class="breadcrumbs-line">
<ul id="new-parent-breadcrumbs" class="breadcrumbs">
</ul>
</div>
</div>
</div>
</div>
</script>
<script type="text/x-template" title="movePageErrors">
<div id="move-errors" class="hidden warning"></div>
</script>
<script type="text/x-template" title="movePageBreadcrumb">
<li><a class="{2}" title="{3}" tabindex="-1"><span>{0}</span></a></li>
</script>
<script type="text/x-template" title="movePageBreadcrumbLoading">
<li class="loading"><span>Loading breadcrumbs&hellip;</span></li>
</script>
<script type="text/x-template" title="movePageBreadcrumbError">
<li class="warning last"><span>Error retrieving breadcrumbs.</span></li>
</script>
<script type="text/x-template" title="movePageNoMatchingPages">
<ol><li><span class="warning">No matching pages found.</span></li></ol>
</script>
<script type="text/x-template" title="movePageNoMatchingSpaces">
<ol><li><span class="warning">No matching spaces found.</span></li></ol>
</script>
<script type="text/x-template" title="movePageSearchPanel">
<div class="row information">
<div class="inner">
<div class="element">
Search for and select the new parent page for this page and its children.
</div>
</div>
</div>
<div id="move-page-search-container" class="row">
<div class="search-form">
<fieldset>
<legend class="assistive"><span>Search for a New Parent Page</span></legend>
<label for="move-page-search-query" class="assistive">Search keywords</label>
<input class="search-query" id="move-page-search-query">
<label for="move-page-search-space" class="assistive">Search in space</label>
<select id="move-page-search-space" class="search-space" disabled="disabled">
<option value="dubbo" selected="selected">Dubbo</option>
</select>
<input type="button" value="Search">
<div class="description warning">You cannot move this page to another space because you do not have permission to remove it from this space.</div>
</fieldset>
</div>
<div class="search-results">
</div>
</div>
</script>
<script type="text/x-template" title="movePageSearchResultsLoading">
<div class="searching">Searching…</div>
</script>
<script type="text/x-template" title="movePageHistoryPanel">
<div class="row information">
<div class="inner">
<div class="element">
Select the new parent page for this page and its children from your history.
</div>
</div>
</div>
<div id="move-page-search-container" class="row">
<div class="search-results">
</div>
</div>
</script>
<script type="text/x-template" title="movePageHistoryLoading">
<div class="searching">Loading…</div>
</script>
<script type="text/x-template" title="movePageBrowsePanel">
<div class="row information">
<div class="inner">
<div class="element">
Click to select the new parent page for this page and its children.
</div>
</div>
</div>
<div class="tree"></div>
</script>
<script type="text/x-template" title="movePagePanelLoading">
<span>Loading…</span>
</script>
<script type="text/x-template" title="movePageBrowsePanelSpace">
<ul><li id='tree-root-node-item' class='root-node-list-item'><a class='root-node' href='#'>{0}</a></li></ul>
</script>
<script type="text/x-template" title="orderingPagePanel">
<div id="orderingPlaceHolder"></div>
</script>
<script type="text/x-template" title="reorderCheckbox">
<span id="reorderRequirement"><input id="reorderCheck" type="checkbox" name="reorderFlag" title="Choose the position of this page within the list of child pages."/><label for="reorderCheck" title="Choose the position of this page within the list of child pages.">Reorder</label></span>
</script>
<script type="text/x-template" title="move-help-link">
<div class="dialog-help-link">
<a href="http://docs.atlassian.com/confluence/docs-35/Moving+a+Page" target="_blank">Help</a>
</div>
</script>
<script type="text/x-template" title="searchResultsGrid">
<table>
<thead>
<tr class="header">
<th class="search-result-title">Page Title</th>
<th class="search-result-space">Space</th>
<th class="search-result-date">Updated</th>
</tr>
</thead>
</table>
</script>
<script type="text/x-template" title="searchResultsGridCount">
<p class="search-result-count">{0}</p>
</script>
<script type="text/x-template" title="searchResultsGridRow">
<tr class="search-result">
<th class="search-result-title"><a href="{1}" class="content-type-{2}"><span>{0}</span></a></th>
<td class="search-result-space"><a class="space" href="http://10.20.160.198/wiki/display/{4}/" title="{3}">{3}</a></td>
<td class="search-result-date"><span class="date" title="{6}">{5}</span></td>
</tr>
</script>
<!-- Start restrictions section -->
<script type="text/x-template" title="page-permissions-div">
<div id="page-permissions-div">
<div id="page-permissions-editor-form">
<div id="page-permissions-error-div" class="hidden">
<a href="#" id="permissions-error-div-close">Ok</a>
<div></div>
</div>
<div id="page-permissions-type-radios" class="page-permissions-label-rows">
<div>
<input id="restrictViewRadio" type="radio" checked="checked" name="pagePermissionTypeRadio" value="view"/>
<label for="restrictViewRadio">Restrict viewing of this page</label>
<input id="restrictEditRadio" type="radio" name="pagePermissionTypeRadio" value="edit"/>
<label for="restrictEditRadio">Restrict editing of this page</label>
</div>
</div>
<div id="page-permissions-input" class="page-permissions-label-rows">
<div class="page-permissions-label">To:</div>
<div id="page-permissions-chooser-box">
<span id="page-permissions-choose-user" class="ajs-button">
<a href="#" id='userpicker-popup-link-image' onClick="var picker = window.open('http://10.20.160.198/wiki/spaces/openuserpicker.action?key=dubbo&startIndex=0&onPopupSubmit=AJS.PagePermissions.addUserPermissions', 'EntitiesPicker', 'status=yes,resizable=yes,top=100,left=200,width=700,height=680,scrollbars=yes'); picker.focus(); return false;"><img src="user_16.gif"/*tpa=http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/user_16.gif*/ height=16 width=16 border=0 align="absmiddle" title="Choose users" /></a>
<a href="#" id='userpicker-popup-link-text' onClick="var picker = window.open('http://10.20.160.198/wiki/spaces/openuserpicker.action?key=dubbo&startIndex=0&onPopupSubmit=AJS.PagePermissions.addUserPermissions', 'EntitiesPicker', 'status=yes,resizable=yes,top=100,left=200,width=700,height=680,scrollbars=yes'); picker.focus(); return false;">Person...</a>
</span>
<span id="page-permissions-choose-group" class="ajs-button">
<a href="#" id='grouppicker-popup-link-image' onClick="var picker = window.open('http://10.20.160.198/wiki/spaces/opengrouppicker.action?key=dubbo&startIndex=0&actionName=dosearchgroups.action&onPopupSubmit=AJS.PagePermissions.addGroupPermissions', 'EntitiesPicker', 'status=yes,resizable=yes,top=100,left=200,width=580,height=550,scrollbars=yes'); picker.focus(); return false;"><img src="group_16.gif"/*tpa=http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/group_16.gif*/ height=16 width=16 border=0 align="absmiddle" title="Choose groups" /></a>
<a href="#" id='grouppicker-popup-link-text' onClick="var picker = window.open('http://10.20.160.198/wiki/spaces/opengrouppicker.action?key=dubbo&startIndex=0&actionName=dosearchgroups.action&onPopupSubmit=AJS.PagePermissions.addGroupPermissions', 'EntitiesPicker', 'status=yes,resizable=yes,top=100,left=200,width=580,height=550,scrollbars=yes'); picker.focus(); return false;">Group...</a>
</span>
</div>
<div id="page-permissions-input-box">
<span>
<input type="text" id="page-permissions-names-input" class="input-placeholder" value="Enter user or group name" name="permissionNames" size="30" autocomplete="off"/>
</span>
<input
type="hidden"
id="page-permissions-names-hidden" /> <img height="16px" width="1px" src="spacer.gif"/*tpa=http://10.20.160.198/wiki/s/en/2166/34/_/images/border/spacer.gif*//>
<input type="button" id="add-typed-names" value="Restrict">
</div>
</div>
</div>
<div id="page-permissions-tables">
<div id="page-permissions-table-div">
<table id="page-permissions-table" class="page-permissions-table">
<tr id="page-permissions-no-views" class="marker-row">
<td colspan="3" class="page-permissions-marker-cell"><span>No view restrictions are defined for this page</span></td>
</tr>
<tr id="page-permissions-no-edits" class="marker-row">
<td colspan="3" class="page-permissions-marker-cell"><span>No edit restrictions are defined for this page</span></td>
</tr>
</table>
</div>
<div id="page-inherited-permissions-table-div" class="hidden">
<span id="page-inherited-permissions-table-desc">
<a class="icon twisty-closed">Show/Hide</a>
<a id="toggle-inherited-permissions" title="Click to see inherited restrictions">This page has restricted parent pages. It can only be seen by users who can see those parent pages.</a>
</span>
<div id="page-inherited-permissions-tables" class="hidden page-inheritance-togglable"></div>
</div>
</div>
</div>
</script>
<script type="text/x-template" title="permissions-row-template">
<tr class="permission-row">
<td class="page-permissions-marker-cell" width="20%">
<span>Viewing restricted to:</span>
</td>
<td class="permission-entity" nowrap="true" width="40%">
<span class="entity-container">
<img class="permission-entity-picture"/>
<span class="permission-entity-display-name"></span>
<span class="permission-entity-name-wrap">&nbsp;(<span class="permission-entity-name"></span>)</span>
</span>
</td>
<td class="permission-detail-column">
<div class="permission-remove-div">
<a href="#" class="remove-permission-link">Remove restriction</a>
</div>
</td>
</tr>
</script>
<script type="text/x-template" title="permissions-username-no-suggestion-template">
<ol>
<li><a href="#" class="message"><span>No matches</span></a></li>
</ol>
</script>
<script type="text/x-template" title="page-inherited-permissions-table-div-template">
<div class="page-inherited-permissions-owner-div">
<div class="page-inherited-permissions-table-desc">Viewing restrictions apply to “<a></a>”. In order to see “<span></span>”, a user must be in the following list of users and groups:</div>
<table class="page-permissions-table"></table>
</div>
</script>
<script type="text/x-template" title="page-restrictions-help-link">
<div class="dialog-help-link">
<a href="http://docs.atlassian.com/confluence/docs-35/Page+Restrictions" target="_blank">Help</a>
</div>
</script>
<!-- End restrictions section -->
<fieldset class="hidden parameters">
<input type="hidden" title="spaceKeyEncoded" value="dubbo">
<input type="hidden" title="spaceKeyDecoded" value="dubbo">
</fieldset>
<a href="#page-metadata-end" class="assistive">Skip to end of metadata</a>
<div id="page-metadata-start" class="assistive"></div>
<div class="page-metadata">
<ul>
<li class="page-metadata-item noprint">
<a id="content-metadata-page-restrictions" href="#" class="page-metadata-icon page-restrictions hidden" title="Page restrictions apply. Click the lock icon to view or edit the restriction.">
<span>Page restrictions apply</span></a> </li>
<li class="page-metadata-modification-info" style="display: none">
Added by <a href="javascript:if(confirm(%27http://10.20.160.198/wiki/display/~william.liangf \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/display/~william.liangf%27" tppabs="http://10.20.160.198/wiki/display/~william.liangf"
class="url fn confluence-userlink" data-username="william.liangf"
>梁 飞</a>, last edited by <a href="javascript:if(confirm(%27http://10.20.160.198/wiki/display/~ding.lid \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/display/~ding.lid%27" tppabs="http://10.20.160.198/wiki/display/~ding.lid"
class="url fn confluence-userlink" data-username="ding.lid"
>李 鼎</a> on 一月 25, 2013
<span class="noprint">&nbsp;(<a id="view-change-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/diffpages.action?pageId=6948815&originalId=8356096 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/diffpages.action?pageId=6948815&originalId=8356096%27" tppabs="http://10.20.160.198/wiki/pages/diffpages.action?pageId=6948815&originalId=8356096">view change</a>)</span>
</li>
</ul>
<div id="version-comment" class="noteMacro" style="display: none;">
<strong>Comment:</strong>
<br />
</div>
</div>
<a href="#page-metadata-start" class="assistive">Go to start of metadata</a>
<div id="page-metadata-end" class="assistive"></div>
<fieldset class="hidden parameters">
<input type="hidden" title="browsePageTreeMode" value="view">
<input type="hidden" title="parentPageId" value="6948805">
</fieldset>
<div class="wiki-content">
<!-- wiki content -->
<table class="sectionMacro" border="0" cellpadding="5" cellspacing="0" width="100%"><tbody><tr><td class="confluenceTd" valign="top"><p><br class="atl-forced-newline" /></p>
<p><a href="Home-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Home-zh" title="Home-zh"><b>首页</b></a> &nbsp;&#124;&#124;&nbsp; <a href="Download-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Download-zh" title="Download-zh"><b>下载</b></a> &nbsp;&#124;&#124;&nbsp; <a href="User+Guide-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/User+Guide-zh" title="User Guide-zh"><b>用户指南</b></a> &nbsp;&#124;&#124;&nbsp; <a href="Developer+Guide-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh" title="Developer Guide-zh"><b>开发者指南</b></a> &nbsp;&#124;&#124;&nbsp; <a href="Administrator+Guide-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Administrator+Guide-zh" title="Administrator Guide-zh"><b>管理员指南</b></a> &nbsp;&#124;&#124;&nbsp; <a href="Training-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Training-zh" title="Training-zh"><b>培训文档</b></a> &nbsp;&#124;&#124;&nbsp; <a href="FAQ-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/FAQ-zh" title="FAQ-zh"><b>常见问题解答</b></a> &nbsp;&#124;&#124;&nbsp; <a href="Release+Notes-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Release+Notes-zh" title="Release Notes-zh"><b>发布记录</b></a> &nbsp;&#124;&#124;&nbsp; <a href="Roadmap-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Roadmap-zh" title="Roadmap-zh"><b>发展路线</b></a> &nbsp;&#124;&#124;&nbsp; <a href="Community-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Community-zh" title="Community-zh"><b>社区</b></a></p></td><td class="confluenceTd" valign="top">
<p><a href="Developer+Guide.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide" title="Developer Guide"><b>English</b></a> | 中文</p></td></tr></tbody></table>
<h1><a name="DeveloperGuide-zh-%E5%BC%80%E5%8F%91%E8%80%85%E6%8C%87%E5%8D%97"></a>开发者指南</h1>
<div>
<ul>
<li><a href='#DeveloperGuide-zh-%E5%8F%82%E4%B8%8E'>参与</a></li>
<ul>
<li><a href='#DeveloperGuide-zh-%E6%B5%81%E7%A8%8B'>流程</a></li>
<li><a href='#DeveloperGuide-zh-%E4%BB%BB%E5%8A%A1'>任务</a></li>
</ul>
<li><a href='#DeveloperGuide-zh-%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86'>版本管理</a></li>
<li><a href='#DeveloperGuide-zh-%E6%BA%90%E7%A0%81%E6%9E%84%E5%BB%BA'>源码构建</a></li>
<li><a href='#DeveloperGuide-zh-%E6%A1%86%E6%9E%B6%E8%AE%BE%E8%AE%A1'>框架设计</a></li>
<ul>
<li><a href='#DeveloperGuide-zh-%E6%95%B4%E4%BD%93%E8%AE%BE%E8%AE%A1'>整体设计</a></li>
<li><a href='#DeveloperGuide-zh-%E6%A8%A1%E5%9D%97%E5%88%86%E5%8C%85'>模块分包</a></li>
<li><a href='#DeveloperGuide-zh-%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB'>依赖关系</a></li>
<li><a href='#DeveloperGuide-zh-%E8%B0%83%E7%94%A8%E9%93%BE'>调用链</a></li>
<li><a href='#DeveloperGuide-zh-%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1%E6%97%B6%E5%BA%8F'>暴露服务时序</a></li>
<li><a href='#DeveloperGuide-zh-%E5%BC%95%E7%94%A8%E6%9C%8D%E5%8A%A1%E6%97%B6%E5%BA%8F'>引用服务时序</a></li>
<li><a href='#DeveloperGuide-zh-%E9%A2%86%E5%9F%9F%E6%A8%A1%E5%9E%8B'>领域模型</a></li>
<li><a href='#DeveloperGuide-zh-%E5%9F%BA%E6%9C%AC%E5%8E%9F%E5%88%99'>基本原则</a></li>
</ul>
<li><a href='#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E5%8A%A0%E8%BD%BD'>扩展点加载</a></li>
<ul>
<li><a href='#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E9%85%8D%E7%BD%AE'>扩展点配置</a></li>
<li><a href='#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E5%8A%A8%E5%8C%85%E8%A3%85'>扩展点自动包装</a></li>
<li><a href='#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D'>扩展点自动装配</a></li>
<li><a href='#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E9%80%82%E5%BA%94'>扩展点自适应</a></li>
<li><a href='#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E5%8A%A8%E6%BF%80%E6%B4%BB'>扩展点自动激活</a></li>
</ul>
<li><a href='#DeveloperGuide-zh-%E5%AE%9E%E7%8E%B0%E7%BB%86%E8%8A%82'>实现细节</a></li>
<ul>
<li><a href='#DeveloperGuide-zh-%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%87%E7%A8%8B%E7%BB%86%E8%8A%82'>初始化过程细节</a></li>
<li><a href='#DeveloperGuide-zh-%E8%BF%9C%E7%A8%8B%E8%B0%83%E7%94%A8%E7%BB%86%E8%8A%82'>远程调用细节</a></li>
<li><a href='#DeveloperGuide-zh-%E8%BF%9C%E7%A8%8B%E9%80%9A%E8%AE%AF%E7%BB%86%E8%8A%82'>远程通讯细节</a></li>
</ul>
<li><a href='#DeveloperGuide-zh-SPI%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C'>SPI参考手册</a></li>
<ul>
<li><a href='#DeveloperGuide-zh-%E5%8D%8F%E8%AE%AE%E6%89%A9%E5%B1%95'>协议扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E8%B0%83%E7%94%A8%E6%8B%A6%E6%88%AA%E6%89%A9%E5%B1%95'>调用拦截扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E5%BC%95%E7%94%A8%E7%9B%91%E5%90%AC%E6%89%A9%E5%B1%95'>引用监听扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E6%9A%B4%E9%9C%B2%E7%9B%91%E5%90%AC%E6%89%A9%E5%B1%95'>暴露监听扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E9%9B%86%E7%BE%A4%E6%89%A9%E5%B1%95'>集群扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E8%B7%AF%E7%94%B1%E6%89%A9%E5%B1%95'>路由扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%89%A9%E5%B1%95'>负载均衡扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E5%90%88%E5%B9%B6%E7%BB%93%E6%9E%9C%E6%89%A9%E5%B1%95'>合并结果扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%89%A9%E5%B1%95'>注册中心扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E7%9B%91%E6%8E%A7%E4%B8%AD%E5%BF%83%E6%89%A9%E5%B1%95'>监控中心扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E5%8A%A0%E8%BD%BD%E6%89%A9%E5%B1%95'>扩展点加载扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E6%89%A9%E5%B1%95'>动态代理扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E7%BC%96%E8%AF%91%E5%99%A8%E6%89%A9%E5%B1%95'>编译器扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E6%B6%88%E6%81%AF%E6%B4%BE%E5%8F%91%E6%89%A9%E5%B1%95'>消息派发扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%89%A9%E5%B1%95'>线程池扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E5%BA%8F%E5%88%97%E5%8C%96%E6%89%A9%E5%B1%95'>序列化扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E7%BD%91%E7%BB%9C%E4%BC%A0%E8%BE%93%E6%89%A9%E5%B1%95'>网络传输扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E4%BF%A1%E6%81%AF%E4%BA%A4%E6%8D%A2%E6%89%A9%E5%B1%95'>信息交换扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E7%BB%84%E7%BD%91%E6%89%A9%E5%B1%95'>组网扩展</a></li>
<li><a href='#DeveloperGuide-zh-Telnet%E5%91%BD%E4%BB%A4%E6%89%A9%E5%B1%95'>Telnet命令扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E7%8A%B6%E6%80%81%E6%A3%80%E6%9F%A5%E6%89%A9%E5%B1%95'>状态检查扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E5%AE%B9%E5%99%A8%E6%89%A9%E5%B1%95'>容器扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E9%A1%B5%E9%9D%A2%E6%89%A9%E5%B1%95'>页面扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E7%BC%93%E5%AD%98%E6%89%A9%E5%B1%95'>缓存扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E9%AA%8C%E8%AF%81%E6%89%A9%E5%B1%95'>验证扩展</a></li>
<li><a href='#DeveloperGuide-zh-%E6%97%A5%E5%BF%97%E9%80%82%E9%85%8D%E6%89%A9%E5%B1%95'>日志适配扩展</a></li>
</ul>
<li><a href='#DeveloperGuide-zh-%E6%8A%80%E6%9C%AF%E5%85%BC%E5%AE%B9%E6%80%A7%E6%B5%8B%E8%AF%95'>技术兼容性测试</a></li>
<ul>
<li><a href='#DeveloperGuide-zh-ProtocolTCK'>Protocol TCK</a></li>
<li><a href='#DeveloperGuide-zh-RegistryTCK'>Registry TCK</a></li>
</ul>
<li><a href='#DeveloperGuide-zh-%E5%85%AC%E5%85%B1%E5%A5%91%E7%BA%A6'>公共契约</a></li>
<ul>
<li><a href='#DeveloperGuide-zh-URL'>URL</a></li>
<li><a href='#DeveloperGuide-zh-%E6%97%A5%E5%BF%97'>日志</a></li>
</ul>
<li><a href='#DeveloperGuide-zh-%E5%9D%8F%E5%91%B3%E9%81%93'>坏味道</a></li>
<ul>
<li><a href='#DeveloperGuide-zh-URL%E8%BD%AC%E6%8D%A2'>URL转换</a></li>
<li><a href='#DeveloperGuide-zh-%E8%B0%83%E7%94%A8%E5%8F%82%E6%95%B0'>调用参数</a></li>
<li><a href='#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E7%9A%84%E5%8A%A0%E8%BD%BD'>扩展点的加载</a></li>
<li><a href='#DeveloperGuide-zh-Callback%E5%8A%9F%E8%83%BD'>Callback功能</a></li>
<li><a href='#DeveloperGuide-zh-Lazy%E8%BF%9E%E6%8E%A5'>Lazy连接</a></li>
<li><a href='#DeveloperGuide-zh-%E5%85%B1%E4%BA%AB%E8%BF%9E%E6%8E%A5'>共享连接</a></li>
<li><a href='#DeveloperGuide-zh-sticky%E7%AD%96%E7%95%A5'>sticky 策略</a></li>
<li><a href='#DeveloperGuide-zh-%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E9%80%89%E6%8B%A9%E9%80%BB%E8%BE%91'>服务提供者选择逻辑</a></li>
</ul>
<li><a href='#DeveloperGuide-zh-%E7%BC%96%E7%A0%81%E7%BA%A6%E5%AE%9A'>编码约定</a></li>
<li><a href='#DeveloperGuide-zh-%E6%A3%80%E6%9F%A5%E5%88%97%E8%A1%A8'>检查列表</a></li>
<li><a href='#DeveloperGuide-zh-%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99'>设计原则</a></li>
</ul></div>
<h2><a name="DeveloperGuide-zh-%E5%8F%82%E4%B8%8E"></a>参与</h2>
<p>(<a href="Getting+Involved-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Getting+Involved-zh" title="Getting Involved-zh">+</a>) (<a href="#DeveloperGuide-zh-%E5%8F%82%E4%B8%8E">&#35;</a>)</p>
<h3><a name="DeveloperGuide-zh-%E6%B5%81%E7%A8%8B"></a>流程</h3>
<p>(<a href="#DeveloperGuide-zh-%E6%B5%81%E7%A8%8B">&#35;</a>)</p>
<p>1. 如果是扩展功能,直接新增工程,黑盒依赖Dubbo进行扩展。<br/>
2. 如果是改BUG,或修改框架本身,可以从<a href="javascript:if(confirm(%27http://code.alibabatech.com/svn/dubbo/trunk/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://code.alibabatech.com/svn/dubbo/trunk/%27" tppabs="http://code.alibabatech.com/svn/dubbo/trunk/" class="external-link" rel="nofollow">Dubb的GitHub</a>上Fork工程。<br/>
3. 修改后通过Push Request反馈修改。</p>
<h3><a name="DeveloperGuide-zh-%E4%BB%BB%E5%8A%A1"></a>任务</h3>
<p>(<a href="#DeveloperGuide-zh-%E4%BB%BB%E5%8A%A1">&#35;</a>)</p>
<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> 《用户指南》翻译 </td>
<td class='confluenceTd'> 文档 </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> 《开发指南》翻译 </td>
<td class='confluenceTd'> 文档 </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> 扩展点<a href="javascript:if(confirm(%27http://en.wikipedia.org/wiki/Technology_Compatibility_Kit \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://en.wikipedia.org/wiki/Technology_Compatibility_Kit%27" tppabs="http://en.wikipedia.org/wiki/Technology_Compatibility_Kit" class="external-link" rel="nofollow">兼容性</a>测试 </td>
<td class='confluenceTd'> 测试 </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> <font color="green">已认领</font> </td>
<td class='confluenceTd'> 罗立树 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> 性能<a href="javascript:if(confirm(%27http://en.wikipedia.org/wiki/Benchmark_(computing) \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://en.wikipedia.org/wiki/Benchmark_(computing)%27" tppabs="http://en.wikipedia.org/wiki/Benchmark_(computing)" class="external-link" rel="nofollow">基准</a>测试 </td>
<td class='confluenceTd'> 测试 </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> 功能<a href="javascript:if(confirm(%27http://en.wikipedia.org/wiki/Unit_testing \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://en.wikipedia.org/wiki/Unit_testing%27" tppabs="http://en.wikipedia.org/wiki/Unit_testing" class="external-link" rel="nofollow">单元</a>测试 </td>
<td class='confluenceTd'> 测试 </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://www.oracle.com/technetwork/java/javaee/jta/index.html \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.oracle.com/technetwork/java/javaee/jta/index.html%27" tppabs="http://www.oracle.com/technetwork/java/javaee/jta/index.html" class="external-link" rel="nofollow">JTA/XA</a>分布式事务 </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Filter">拦截扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://thrift.apache.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://thrift.apache.org/%27" tppabs="http://thrift.apache.org/" class="external-link" rel="nofollow">Thrift</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Protocol">协议扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 开发完成 </td>
<td class='confluenceTd'> 闾刚 </td>
<td class='confluenceTd'> 2012-04-27 </td>
<td class='confluenceTd'> 90% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://www.zeroc.com/ice.html \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.zeroc.com/ice.html%27" tppabs="http://www.zeroc.com/ice.html" class="external-link" rel="nofollow">ICE</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Protocol">协议扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://www.cs.wustl.edu/~schmidt/ACE.html \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.cs.wustl.edu/~schmidt/ACE.html%27" tppabs="http://www.cs.wustl.edu/~schmidt/ACE.html" class="external-link" rel="nofollow">ACE</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Protocol">协议扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://json-rpc.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://json-rpc.org/%27" tppabs="http://json-rpc.org/" class="external-link" rel="nofollow">JSON-RPC</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Protocol">协议扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://www.xmlrpc.com/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.xmlrpc.com/%27" tppabs="http://www.xmlrpc.com/" class="external-link" rel="nofollow">XML-RPC</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Protocol">协议扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://jcp.org/en/jsr/detail?id=181 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://jcp.org/en/jsr/detail?id=181%27" tppabs="http://jcp.org/en/jsr/detail?id=181" class="external-link" rel="nofollow">JSR181</a>&amp;<a href="javascript:if(confirm(%27http://cxf.apache.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://cxf.apache.org/%27" tppabs="http://cxf.apache.org/" class="external-link" rel="nofollow">CXF</a>(WebService) </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Protocol">协议扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 开发完成 </td>
<td class='confluenceTd'> 白文志 </td>
<td class='confluenceTd'> 2012-04-27 </td>
<td class='confluenceTd'> 90% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://jcp.org/en/jsr/detail?id=311 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://jcp.org/en/jsr/detail?id=311%27" tppabs="http://jcp.org/en/jsr/detail?id=311" class="external-link" rel="nofollow">JSR311</a>&amp;<a href="javascript:if(confirm(%27http://jcp.org/en/jsr/detail?id=339 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://jcp.org/en/jsr/detail?id=339%27" tppabs="http://jcp.org/en/jsr/detail?id=339" class="external-link" rel="nofollow">JSR339</a>(RestfulWebService) </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Protocol">协议扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://jcp.org/en/jsr/detail?id=914 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://jcp.org/en/jsr/detail?id=914%27" tppabs="http://jcp.org/en/jsr/detail?id=914" class="external-link" rel="nofollow">JMS</a>&amp;<a href="javascript:if(confirm(%27http://activemq.apache.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://activemq.apache.org/%27" tppabs="http://activemq.apache.org/" class="external-link" rel="nofollow">ActiveMQ</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Protocol">协议扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://code.google.com/p/protobuf \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://code.google.com/p/protobuf%27" tppabs="http://code.google.com/p/protobuf" class="external-link" rel="nofollow">Protobuf</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Serialization">序列化扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 调研 </td>
<td class='confluenceTd'> 朱启恒 </td>
<td class='confluenceTd'> 2012-02-30 </td>
<td class='confluenceTd'> 20% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://avro.apache.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://avro.apache.org/%27" tppabs="http://avro.apache.org/" class="external-link" rel="nofollow">Avro</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Serialization">序列化扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://xsocket.sourceforge.net/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://xsocket.sourceforge.net/%27" tppabs="http://xsocket.sourceforge.net/" class="external-link" rel="nofollow">XSocket</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-Transporter">传输扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://cglib.sourceforge.net/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://cglib.sourceforge.net/%27" tppabs="http://cglib.sourceforge.net/" class="external-link" rel="nofollow">CGLib</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-ProxyFactory">动态代理扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://www.oracle.com/technetwork/java/jndi/index.html \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.oracle.com/technetwork/java/jndi/index.html%27" tppabs="http://www.oracle.com/technetwork/java/jndi/index.html" class="external-link" rel="nofollow">JNDI</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-RegistryFactory">注册中心扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://www.openldap.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.openldap.org/%27" tppabs="http://www.openldap.org/" class="external-link" rel="nofollow">LDAP</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-RegistryFactory">注册中心扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://jcp.org/en/jsr/detail?id=140 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://jcp.org/en/jsr/detail?id=140%27" tppabs="http://jcp.org/en/jsr/detail?id=140" class="external-link" rel="nofollow">JSR140</a>&amp;<a href="javascript:if(confirm(%27http://jslp.sourceforge.net/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://jslp.sourceforge.net/%27" tppabs="http://jslp.sourceforge.net/" class="external-link" rel="nofollow">SLP</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-RegistryFactory">注册中心扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://thrift.apache.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://thrift.apache.org/%27" tppabs="http://thrift.apache.org/" class="external-link" rel="nofollow">UDDI</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-RegistryFactory">注册中心扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://thrift.apache.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://thrift.apache.org/%27" tppabs="http://thrift.apache.org/" class="external-link" rel="nofollow">JMX</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-MonitorFactory">监控中心扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://www.snmp4j.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.snmp4j.org/%27" tppabs="http://www.snmp4j.org/" class="external-link" rel="nofollow">SNMP</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-MonitorFactory">监控中心扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://www.cacti.net/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.cacti.net/%27" tppabs="http://www.cacti.net/" class="external-link" rel="nofollow">Cacti</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-MonitorFactory">监控中心扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://www.nagios.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.nagios.org/%27" tppabs="http://www.nagios.org/" class="external-link" rel="nofollow">Nagios</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-MonitorFactory">监控中心扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://logstash.net/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://logstash.net/%27" tppabs="http://logstash.net/" class="external-link" rel="nofollow">Logstash</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-MonitorFactory">监控中心扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://www.jrobin.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.jrobin.org/%27" tppabs="http://www.jrobin.org/" class="external-link" rel="nofollow">JRobin</a> </td>
<td class='confluenceTd'> <a href="#DeveloperGuide-zh-MonitorFactory">监控中心扩展</a> </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://maven.apache.org/wagon \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://maven.apache.org/wagon%27" tppabs="http://maven.apache.org/wagon" class="external-link" rel="nofollow">Maven</a> </td>
<td class='confluenceTd'> 服务安装包仓库 </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://subversion.apache.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://subversion.apache.org/%27" tppabs="http://subversion.apache.org/" class="external-link" rel="nofollow">Subversion</a> </td>
<td class='confluenceTd'> 服务安装包仓库 </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="javascript:if(confirm(%27http://jcp.org/en/jsr/detail?id=283 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://jcp.org/en/jsr/detail?id=283%27" tppabs="http://jcp.org/en/jsr/detail?id=283" class="external-link" rel="nofollow">JCR/JSR283</a> </td>
<td class='confluenceTd'> 服务安装包仓库 </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<th class='confluenceTh'> 功能 </th>
<th class='confluenceTh'> 分类 </th>
<th class='confluenceTh'> 优先级 </th>
<th class='confluenceTh'> 状态 </th>
<th class='confluenceTh'> 认领者 </th>
<th class='confluenceTh'> 计划完成时间 </th>
<th class='confluenceTh'> 进度 </th>
</tr>
<tr>
<td class='confluenceTd'> SimpleDeployer </td>
<td class='confluenceTd'> 本地部署代理 </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
<tr>
<td class='confluenceTd'> SimpleScheduler </td>
<td class='confluenceTd'> 资源调度器 </td>
<td class='confluenceTd'></td>
<td class='confluenceTd'> 未认领 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 待定 </td>
<td class='confluenceTd'> 0% </td>
</tr>
</tbody></table>
</div>
<h2><a name="DeveloperGuide-zh-%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86"></a>版本管理</h2>
<p>(<a href="Version+Management-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Version+Management-zh" title="Version Management-zh">+</a>) (<a href="#DeveloperGuide-zh-%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86">&#35;</a>)</p>
<p><b>新功能的开发</b><b>稳定性的提高</b> 对产品都很重要。</p>
<p>但是添加新功能对影响稳定性,Dubbo使用如下的版本开发模式来保障两者。</p>
<h4><a name="DeveloperGuide-zh-2%E4%B8%AA%E7%89%88%E6%9C%AC%E5%B9%B6%E8%A1%8C%E5%BC%80%E5%8F%91"></a>2个版本并行开发</h4>
<ul>
<li><b>BugFix版本</b>,低版本,比如2.4.x。是<b>GA版本</b>,线上使用的版本,只会BugFix,升级第三位版本号。<br/>
&#35; 这个版本可放在SVN的Fix分支上。</li>
<li><b>新功能版本</b>,高版本,比如2.5.x。加新功能的版本,会给对新功能有需求的应用试用。<br/>
&#35; 这个版本可放在SVN的Trunk上。</li>
</ul>
<p>2.5.x的新功能基本稳定后,进入2.5.x试用阶段。找足够多的应用试用2.5.x版本。</p>
<p>在2.5.x够稳定后:</p>
<ol>
<li>2.5.x成为GA版本,只BugFix,推广使用此版本。<br/>
&#35; 如何可行,可以推进应用在期望的时间点内升级到GA版本。</li>
<li>2.4.x<b>不再</b>开发,应用碰到Bug让直接升级。(这个称为“<b>夕阳条款</b>”)</li>
<li>从2.5.x拉成分支2.6.0,作为新功能开发版本。</li>
</ol>
<h4><a name="DeveloperGuide-zh-%E4%BC%98%E5%8A%BF"></a>优势</h4>
<ul>
<li>保持GA版本是稳定的!因为:
<ul>
<li>只会作BugFix</li>
<li>成为GA版本前有试用阶段</li>
</ul>
</li>
<li>新功能可以高版本中快速响应,并让应用能试用新功能。</li>
<li>不会版本过多,导致开发和维护成本剧增</li>
</ul>
<h4><a name="DeveloperGuide-zh-%E7%94%A8%E6%88%B7%E8%A6%81%E9%85%8D%E5%90%88%E7%9A%84%E8%81%8C%E8%B4%A3"></a>用户要配合的职责</h4>
<p>由于开发只会BugFix GA版本,所以用户需要积极跟进升级到GA版本,以Fix发现的问题。</p>
<p>定期升级版本用户带来了不安。这是一个伪命题,说明如下:</p>
<ul>
<li>GA经过一个试用阶段保持稳定。</li>
<li>GA版本有Bug会火速Fix</li>
<li>相对出问题才升级到GA版本(可以跨了多个版本)定期升级平摊风险(类似小步快跑)。<br/>
经历过周期长的大项目的同学会有这样的经历,三方库版本不时间不升级,结果出了问题不得不升级到新版本(跨了多个版本)风险巨大。</li>
</ul>
<h2><a name="DeveloperGuide-zh-%E6%BA%90%E7%A0%81%E6%9E%84%E5%BB%BA"></a>源码构建</h2>
<p>(<a href="Source+Building-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Source+Building-zh" title="Source Building-zh">+</a>) (<a href="#DeveloperGuide-zh-%E6%BA%90%E7%A0%81%E6%9E%84%E5%BB%BA">#</a>)</p>
<h4><a name="DeveloperGuide-zh-Browser%3A"></a>Browser:</h4>
<p>To browse the source tree directly:</p>
<p><a href="javascript:if(confirm(%27https://github.com/alibaba/dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27https://github.com/alibaba/dubbo%27" tppabs="https://github.com/alibaba/dubbo" class="external-link" rel="nofollow">https://github.com/alibaba/dubbo</a></p>
<h4><a name="DeveloperGuide-zh-Git%3A"></a>Git:</h4>
<p>Use this command to check out the latest project source code:</p>
<div class="panel" style="background-color: white;border-width: 1px;"><div class="panelContent" style="background-color: white;">
<p>git clone <a href="javascript:if(confirm(%27https://github.com/alibaba/dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27https://github.com/alibaba/dubbo%27" tppabs="https://github.com/alibaba/dubbo" class="external-link" rel="nofollow">https://github.com/alibaba/dubbo</a> dubbo</p>
</div></div>
<p>Powered by: <a href="javascript:if(confirm(%27http://git-scm.com/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://git-scm.com/%27" tppabs="http://git-scm.com/" class="external-link" rel="nofollow">Git</a></p>
<h4><a name="DeveloperGuide-zh-Branches"></a>Branches</h4>
<p>We use the trunk for the next main release; then we use a branch for any bug fixes on the previous major release. You can look at all branches here:</p>
<p><a href="javascript:if(confirm(%27https://github.com/alibaba/dubbo/tags \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27https://github.com/alibaba/dubbo/tags%27" tppabs="https://github.com/alibaba/dubbo/tags" class="external-link" rel="nofollow">https://github.com/alibaba/dubbo/tags</a></p>
<h4><a name="DeveloperGuide-zh-Building"></a>Building</h4>
<p>Dubbo uses <a href="javascript:if(confirm(%27http://maven.apache.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://maven.apache.org/%27" tppabs="http://maven.apache.org/" class="external-link" rel="nofollow">Maven</a> as its build tool. If you don't fancy using Maven you can use your IDE directly or <a href="Download.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Download" title="Download">Download</a> a distribution or JAR.</p>
<h5><a name="DeveloperGuide-zh-Required%3A"></a>Required:</h5>
<ul>
<li>Java 1.5 or better</li>
<li>Download and install Maven 2.2.1 or better.</li>
<li>Get the latest Source
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[svn checkout http://code.alibabatech.com/svn/dubbo/trunk dubbo]]></script>
</div></div></li>
</ul>
<h5><a name="DeveloperGuide-zh-Mavenoptions"></a>Maven options</h5>
<p>To build dubbo maven has to be configured to use more memory</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[set MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=512m]]></script>
</div></div>
<h5><a name="DeveloperGuide-zh-Anormalbuild"></a>A normal build</h5>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[mvn install]]></script>
</div></div>
<h5><a name="DeveloperGuide-zh-DoingaQuickBuild"></a>Doing a Quick Build</h5>
<p>Available as of Dubbo 2.0</p>
<p>The following skips building the manual, the distro and does not execute the unit tests.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[mvn install -Dmaven.test.skip]]></script>
</div></div>
<h5><a name="DeveloperGuide-zh-UsinganIDE"></a>Using an IDE</h5>
<p>If you prefer to use an IDE then you can auto-generate the IDE's project files using maven plugins. e.g.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[mvn eclipse:eclipse]]></script>
</div></div>
<p>or</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[mvn idea:idea]]></script>
</div></div>
<h5><a name="DeveloperGuide-zh-ImportingintoEclipse"></a>Importing into Eclipse</h5>
<p>If you have not already done so, you will need to make Eclipse aware of the Maven repository so that it can build everything. In the preferences, go to Java-&gt;Build Path-&gt;Classpath and define a new Classpath Variable named M2_REPO that points to your local Maven repository (i.e., ~/.m2/repository on Unix and c:\Documents and Settings\&lt;user&gt;\.m2\repository on Windows).</p>
<p>You can also get Maven to do this for you:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[mvn eclipse:configure-workspace -Declipse.workspace=/path/to/the/workspace/]]></script>
</div></div>
<h5><a name="DeveloperGuide-zh-Buildingsourcejars"></a>Building source jars</h5>
<p>If you want to build jar files with the source code, that for instance Eclipse can important so you can debug the Dubbo code as well. Then you can run this command from the dubbo root folder:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[mvn clean source:jar install -Dmaven.test.skip]]></script>
</div></div>
<h2><a name="DeveloperGuide-zh-%E6%A1%86%E6%9E%B6%E8%AE%BE%E8%AE%A1"></a>框架设计</h2>
<p>(<a href="Framework+Design-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Framework+Design-zh" title="Framework Design-zh">+</a>) (<a href="#DeveloperGuide-zh-%E6%A1%86%E6%9E%B6%E8%AE%BE%E8%AE%A1">#</a>)</p>
<h3><a name="DeveloperGuide-zh-%E6%95%B4%E4%BD%93%E8%AE%BE%E8%AE%A1"></a>整体设计</h3>
<p><span class="image-wrap" style=""><img src="dubbo-framework.jpg-version=1&modificationDate=1341329396000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6947196/dubbo-framework.jpg?version=1&modificationDate=1341329396000" style="border: 0px solid black" /></span><br/>
如果你觉得图过于复杂,请查看:<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/download/attachments/6947196/dubbo-framework.gif?version=1&modificationDate=1329224790000 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/download/attachments/6947196/dubbo-framework.gif?version=1&modificationDate=1329224790000%27" tppabs="http://10.20.160.198/wiki/download/attachments/6947196/dubbo-framework.gif?version=1&modificationDate=1329224790000"><b>&gt;&gt;框架图绘制步骤动画</b></a></p>
<h4><a name="DeveloperGuide-zh-%E5%9B%BE%E4%BE%8B%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>图例说明:</h4>
<ul>
<li>图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口, 位于中轴线上的为双方都用到的接口。</li>
<li>图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系,每一层都可以剥离上层被复用,其中,Service和Config层为API,其它各层均为SPI。</li>
<li>图中绿色小块的为扩展接口,蓝色小块为实现类,图中只显示用于关联各层的实现类。</li>
<li>图中蓝色虚线为初始化过程,即启动时组装链,红色实线为方法调用过程,即运行时调时链,紫色三角箭头为继承,可以把子类看作父类的同一个节点,线上的文字为调用的方法。</li>
</ul>
<h4><a name="DeveloperGuide-zh-%E5%90%84%E5%B1%82%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>各层说明:</h4>
<ul>
<li>config,配置层,对外配置接口,以ServiceConfig, ReferenceConfig为中心,可以直接new配置类,也可以通过spring解析配置生成配置类</li>
<li>proxy,服务代理层,服务接口透明代理,生成服务的客户端Stub和服务器端Skeleton,以ServiceProxy为中心,扩展接口为ProxyFactory</li>
<li>registry,注册中心层,封装服务地址的注册与发现,以服务URL为中心,扩展接口为RegistryFactory, Registry, RegistryService</li>
<li>cluster,路由层,封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster, Directory, Router, LoadBalance</li>
<li>monitor,监控层,RPC调用次数和调用时间监控,以Statistics为中心,扩展接口为MonitorFactory, Monitor, MonitorService</li>
<li>protocol,远程调用层,封将RPC调用,以Invocation, Result为中心,扩展接口为Protocol, Invoker, Exporter</li>
<li>exchange,信息交换层,封装请求响应模式,同步转异步,以Request, Response为中心,扩展接口为Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer</li>
<li>transport,网络传输层,抽象mina和netty为统一接口,以Message为中心,扩展接口为Channel, Transporter, Client, Server, Codec</li>
<li>serialize,数据序列化层,可复用的一些工具,扩展接口为Serialization, ObjectInput, ObjectOutput, ThreadPool</li>
</ul>
<h4><a name="DeveloperGuide-zh-%E5%85%B3%E7%B3%BB%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>关系说明:</h4>
<ul>
<li>在RPC中,Protocol是核心层,也就是只要有Protocol + Invoker + Exporter就可以完成非透明的RPC调用,然后在Invoker的主过程上Filter拦截点。</li>
<li>图中的Consumer和Provider是抽象概念,只是想让看图者更直观的了解哪些类分属于客户端与服务器端,不用Client和Server的原因是Dubbo在很多场景下都使用Provider, Consumer, Registry, Monitor划分逻辑拓普节点,保持统一概念。</li>
<li>而Cluster是外围概念,所以Cluster的目的是将多个Invoker伪装成一个Invoker,这样其它人只要关注Protocol层Invoker即可,加上Cluster或者去掉Cluster对其它层都不会造成影响,因为只有一个提供者时,是不需要Cluster的。</li>
<li>Proxy层封装了所有接口的透明化代理,而在其它层都以Invoker为中心,只有到了暴露给用户使用时,才用Proxy将Invoker转成接口,或将接口实现转成Invoker,也就是去掉Proxy层RPC是可以Run的,只是不那么透明,不那么看起来像调本地服务一样调远程服务。</li>
<li>而Remoting实现是Dubbo协议的实现,如果你选择RMI协议,整个Remoting都不会用上,Remoting内部再划为Transport传输层和Exchange信息交换层,Transport层只负责单向消息传输,是对Mina,Netty,Grizzly的抽象,它也可以扩展UDP传输,而Exchange层是在传输层之上封装了Request-Response语义。</li>
<li>Registry和Monitor实际上不算一层,而是一个独立的节点,只是为了全局概览,用层的方式画在一起。</li>
</ul>
<h3><a name="DeveloperGuide-zh-%E6%A8%A1%E5%9D%97%E5%88%86%E5%8C%85"></a>模块分包</h3>
<p><span class="image-wrap" style=""><img src="dubbo-modules.jpg-version=1&modificationDate=1332170734000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6947196/dubbo-modules.jpg?version=1&modificationDate=1332170734000" style="border: 0px solid black" /></span></p>
<p>模块说明:</p>
<ul>
<li>dubbo-common 公共逻辑模块,包括Util类和通用模型。</li>
<li>dubbo-remoting 远程通讯模块,相当于Dubbo协议的实现,如果RPC用RMI协议则不需要使用此包。</li>
<li>dubbo-rpc 远程调用模块,抽象各种协议,以及动态代理,只包含一对一的调用,不关心集群的管理。</li>
<li>dubbo-cluster 集群模块,将多个服务提供方伪装为一个提供方,包括:负载均衡, 容错,路由等,集群的地址列表可以是静态配置的,也可以是由注册中心下发。</li>
<li>dubbo-registry 注册中心模块,基于注册中心下发地址的集群方式,以及对各种注册中心的抽象。</li>
<li>dubbo-monitor 监控模块,统计服务调用次数,调用时间的,调用链跟踪的服务。</li>
<li>dubbo-config 配置模块,是Dubbo对外的API,用户通过Config使用Dubbo,隐藏Dubbo所有细节。</li>
<li>dubbo-container 容器模块,是一个Standlone的容器,以简单的Main加载Spring启动,因为服务通常不需要Tomcat/JBoss等Web容器的特性,没必要用Web容器去加载服务。</li>
</ul>
<p>整体上按照分层结构进行分包,与分层的不同点在于:</p>
<ul>
<li>container为服务容器,用于部署运行服务,没有在层中画出。</li>
<li>protocol层和proxy层都放在rpc模块中,这两层是rpc的核心,在不需要集群时(只有一个提供者),可以只使用这两层完成rpc调用。</li>
<li>transport层和exchange层都放在remoting模块中,为rpc调用的通讯基础。</li>
<li>serialize层放在common模块中,以便更大程度复用。</li>
</ul>
<h3><a name="DeveloperGuide-zh-%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB"></a>依赖关系</h3>
<p><span class="image-wrap" style=""><img src="dubbo-relation.jpg-version=1&modificationDate=1325860239000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6947196/dubbo-relation.jpg?version=1&modificationDate=1325860239000" style="border: 0px solid black" /></span></p>
<h4><a name="DeveloperGuide-zh-%E5%9B%BE%E4%BE%8B%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>图例说明:</h4>
<ul>
<li>图中小方块Protocol, Cluster, Proxy, Service, Container, Registry, Monitor代表层或模块,蓝色的表示与业务有交互,绿色的表示只对Dubbo内部交互。</li>
<li>图中背景方块Consumer, Provider, Registry, Monitor代表部署逻辑拓普节点。</li>
<li>图中蓝色虚线为初始化时调用,红色虚线为运行时异步调用,红色实线为运行时同步调用。</li>
<li>图中只包含RPC的层,不包含Remoting的层,Remoting整体都隐含在Protocol中。</li>
</ul>
<h3><a name="DeveloperGuide-zh-%E8%B0%83%E7%94%A8%E9%93%BE"></a>调用链</h3>
<p>展开总设计图的红色调用链,如下:<br/>
<span class="image-wrap" style=""><img src="dubbo-extension.jpg-version=1&modificationDate=1317370068000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6947196/dubbo-extension.jpg?version=1&modificationDate=1317370068000" style="border: 0px solid black" /></span></p>
<h3><a name="DeveloperGuide-zh-%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1%E6%97%B6%E5%BA%8F"></a>暴露服务时序</h3>
<p>展开总设计图左边服务提供方暴露服务的蓝色初始化链,时序图如下:<br/>
<span class="image-wrap" style=""><img src="dubbo-export.jpg-version=1&modificationDate=1317370076000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6947196/dubbo-export.jpg?version=1&modificationDate=1317370076000" style="border: 0px solid black" /></span></p>
<h3><a name="DeveloperGuide-zh-%E5%BC%95%E7%94%A8%E6%9C%8D%E5%8A%A1%E6%97%B6%E5%BA%8F"></a>引用服务时序</h3>
<p>展开总设计图右边服务消费方引用服务的蓝色初始化链,时序图如下:<br/>
<span class="image-wrap" style=""><img src="dubbo-refer.jpg-version=1&modificationDate=1317370102000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6947196/dubbo-refer.jpg?version=1&modificationDate=1317370102000" style="border: 0px solid black" /></span></p>
<h3><a name="DeveloperGuide-zh-%E9%A2%86%E5%9F%9F%E6%A8%A1%E5%9E%8B"></a>领域模型</h3>
<p>在Dubbo的核心领域模型中:</p>
<ul>
<li>Protocol是服务域,它是Invoker暴露和引用的主功能入口,它负责Invoker的生命周期管理。</li>
<li>Invoker是实体域,它是Dubbo的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起invoke调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。</li>
<li>Invocation是会话域,它持有调用过程中的变量,比如方法名,参数等。</li>
</ul>
<h3><a name="DeveloperGuide-zh-%E5%9F%BA%E6%9C%AC%E5%8E%9F%E5%88%99"></a>基本原则</h3>
<ul>
<li>采用Microkernel + Plugin模式,Microkernel只负责组将Plugin,Dubbo自身的功能也是通过扩展点实现的,也就是Dubbo的所有功能点都可被用户自定义扩展所替换。</li>
<li>采用URL作为配置信息的统一格式,所有扩展点都通过传递URL携带配置信息。</li>
</ul>
<p>更多设计原则参见:<a href="Training-zh.htm#Training-zh-%E3%80%8A%E6%A1%86%E6%9E%B6%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99%E3%80%8B" tppabs="http://10.20.160.198/wiki/display/dubbo/Training-zh#Training-zh-%E3%80%8A%E6%A1%86%E6%9E%B6%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99%E3%80%8B">《框架设计原则》</a></p>
<h2><a name="DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E5%8A%A0%E8%BD%BD"></a>扩展点加载</h2>
<p>(<a href="Extension+Loader-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Extension+Loader-zh" title="Extension Loader-zh">+</a>) (<a href="#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E5%8A%A0%E8%BD%BD">#</a>)</p>
<h3><a name="DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E9%85%8D%E7%BD%AE"></a>扩展点配置</h3>
<p><b>来源:</b></p>
<p>Dubbo的扩展点加载从JDK标准的SPI(Service Provider Interface)扩展点发现机制加强而来。</p>
<p>Dubbo改进了JDK标准的SPI的以下问题:</p>
<ul>
<li>JDK标准的SPI会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。</li>
<li>如果扩展点加载失败,连扩展点的名称都拿不到了。比如:JDK标准的ScriptEngine,通过getName();获取脚本类型的名称,但如果RubyScriptEngine因为所依赖的jruby.jar不存在,导致RubyScriptEngine类加载失败,这个失败原因被吃掉了,和ruby对应不起来,当用户执行ruby脚本时,会报不支持ruby,而不是真正失败的原因。</li>
<li>增加了对扩展点IoC和AOP的支持,一个扩展点可以直接setter注入其它扩展点。</li>
</ul>
<p><b>约定:</b></p>
<p>在扩展类的jar包内,放置扩展点配置文件:META-INF/dubbo/接口全限定名,内容为:配置名=扩展实现类全限定名,多个实现类用换行符分隔。</p>
<p><font color="green">(注意:这里的配置文件是放在你自己的jar包内,不是dubbo本身的jar包内,Dubbo会全ClassPath扫描所有jar包内同名的这个文件,然后进行合并)</font></p>
<p>扩展Dubbo的协议示例:</p>
<p>在协议的实现jar包内放置文本文件:META-INF/dubbo/com.alibaba.dubbo.rpc.Protocol,内容为:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.alibaba.xxx.XxxProtocol]]></script>
</div></div>
<p>实现类内容:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.alibaba.xxx;
import com.alibaba.dubbo.rpc.Protocol;
public class XxxProtocol implemenets Protocol {
// ...
}]]></script>
</div></div>
<p><font color="red">注意: 扩展点使用单一实例加载(请确保扩展实现的</font><font color="red"><b>线程安全</b></font><font color="red">性),Cache在ExtensionLoader中。</font></p>
<h3><a name="DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E5%8A%A8%E5%8C%85%E8%A3%85"></a>扩展点自动包装</h3>
<h6><a name="DeveloperGuide-zh-%E8%87%AA%E5%8A%A8Wrap%E6%89%A9%E5%B1%95%E7%82%B9%E7%9A%84Wrapper%E7%B1%BB"></a>自动Wrap扩展点的Wrapper类</h6>
<p>ExtensionLoader会把加载扩展点时(通过扩展点配置文件中内容),如果该实现有拷贝构造函数,则判定为扩展点Wrapper类。</p>
<p>Wrapper类同样实现了扩展点接口。</p>
<p>Wrapper类内容:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.alibaba.xxx;
import com.alibaba.dubbo.rpc.Protocol;
public class XxxProtocolWrapper implemenets Protocol {
Protocol impl;
public XxxProtocol(Protocol protocol) { impl = protocol; }
// 接口方法做一个操作后,再调用extension的方法
public void refer() {
//... 一些操作
impl .refer();
// ... 一些操作
}
// ...
}]]></script>
</div></div>
<p>Wrapper不是扩展点实现,用于从ExtensionLoader返回扩展点时,Wrap在扩展点实现外。即从ExtensionLoader中返回的实际上是Wrapper类的实例,Wrapper持有了实际的扩展点实现类。</p>
<p>扩展点的Wrapper类可以有多个,也可以根据需要新增。</p>
<p>通过Wrapper类可以把所有扩展点公共逻辑移至Wrapper中。新加的Wrapper在所有的扩展点上添加了逻辑,有些类似AOP(Wraper代理了扩展点)。</p>
<h3><a name="DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D"></a>扩展点自动装配</h3>
<h6><a name="DeveloperGuide-zh-%E5%8A%A0%E8%BD%BD%E6%89%A9%E5%B1%95%E7%82%B9%E6%97%B6%EF%BC%8C%E8%87%AA%E5%8A%A8%E6%B3%A8%E5%85%A5%E4%BE%9D%E8%B5%96%E7%9A%84%E6%89%A9%E5%B1%95%E7%82%B9"></a>加载扩展点时,自动注入依赖的扩展点</h6>
<p>加载扩展点时,扩展点实现类的成员如果为其它扩展点类型,ExtensionLoader在会自动注入依赖的扩展点。</p>
<p>ExtensionLoader通过扫描扩展点实现类的所有set方法来判定其成员。</p>
<p>即ExtensionLoader会执行扩展点的拼装操作。</p>
<p>示例:有两个为扩展点CarMaker(造车者)、wheelMaker(造轮者)</p>
<p>接口类如下:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public interface CarMaker {
Car makeCar();
}
public interface WheelMaker {
Wheel makeWheel();
}]]></script>
</div></div>
<p>CarMaker的一个实现类:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public class RaceCarMaker implemenets CarMaker {
WheelMaker wheelMaker;
public setWheelMaker(WheelMaker wheelMaker) {
this.wheelMaker = wheelMaker;
}
public Car makeCar() {
// ...
Wheel wheel = wheelMaker.makeWheel();
// ...
return new RaceCar(wheel, ...);
}
}]]></script>
</div></div>
<p>ExtensionLoader加载CarMaker的扩展点实现RaceCar时,setWheelMaker方法的WheelMaker也是扩展点则会注入WheelMaker的实现。</p>
<p>这里带来另一个问题,ExtensionLoader要注入依赖扩展点时,如何决定要注入依赖扩展点的哪个实现。在这个示例中,即是在多个WheelMaker的实现中要注入哪个。</p>
<p>这个问题在下面一点“Adaptive实例”中说明。</p>
<h3><a name="DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E9%80%82%E5%BA%94"></a>扩展点自适应</h3>
<h6><a name="DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E7%9A%84Adaptive%E5%AE%9E%E4%BE%8B"></a>扩展点的Adaptive实例</h6>
<p>ExtensionLoader注入的依赖扩展点是一个Adaptive实例,直到扩展点方法执行时才决定调用是一个扩展点实现。</p>
<p>Dubbo使用URL对象(包含了Key-Value)传递配置信息。</p>
<p>扩展点方法调用会有URL参数(或是参数有URL成员)</p>
<p>这样依赖的扩展点也可以从URL拿到配置信息,所有的扩展点自己定好配置的Key后,配置信息从URL上从最外层传入。URL在配置传递上即是一条<b>总线</b></p>
<p>示例:有两个为扩展点CarMaker(造车者)、wheelMaker(造轮者)</p>
<p>接口类如下:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public interface CarMaker {
Car makeCar(URL url);
}
public interface WheelMaker {
Wheel makeWheel(URL url);
}]]></script>
</div></div>
<p>CarMaker的一个实现类:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public class RaceCarMaker implemenets CarMaker {
WheelMaker wheelMaker;
public setWheelMaker(WheelMaker wheelMaker) {
this.wheelMaker = wheelMaker;
}
public Car makeCar(URL url) {
// ...
Wheel wheel = wheelMaker.makeWheel(url);
// ...
return new RaceCar(wheel, ...);
}
}]]></script>
</div></div>
<p>当上面执行</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[// ...
Wheel wheel = wheelMaker.makeWheel(url);
// ...]]></script>
</div></div>
<p>时,注入的Adaptive实例可以提取约定Key来决定使用哪个WheelMaker实现来调用对应实现的真正的makeWheel方法。</p>
<p>如提取wheel.type key即url.get("wheel.type")来决定WheelMake实现。</p>
<p>Adaptive实例的逻辑是固定,指定提取的URL的Key,即可以代理真正的实现类上,可以动态生成。</p>
<p>在Dubbo的ExtensionLoader的扩展点类开对应的Adaptive实现是在加载扩展点里动态生成。指定提取的URL的Key通过@Adaptive注解在接口方法上提供。</p>
<p>下面是Dubbo的Transporter扩展点的代码:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public interface Transporter {
@Adaptive({"server", "transport"})
Server bind(URL url, ChannelHandler handler) throws RemotingException;
@Adaptive({"client", "transport"})
Client connect(URL url, ChannelHandler handler) throws RemotingException;
}]]></script>
</div></div>
<p>对于bind方法表示,Adaptive实现先查找"server"key,如果该Key没有值则找"transport"key值,来决定代理到哪个实际扩展点。</p>
<h5><a name="DeveloperGuide-zh-3.Dubbo%E9%85%8D%E7%BD%AE%E6%A8%A1%E5%9D%97%E4%B8%AD%E6%89%A9%E5%B1%95%E7%82%B9%E7%9A%84%E9%85%8D%E7%BD%AE"></a>3. Dubbo配置模块中扩展点的配置</h5>
<p>Dubbo配置模块中,扩展点均有对应配置属性或标签,通过配置指定使用哪个扩展实现。</p>
<p>比如:&lt;dubbo:protocol name="xxx" /&gt;</p>
<h3><a name="DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E5%8A%A8%E6%BF%80%E6%B4%BB"></a>扩展点自动激活</h3>
<p>对于集合类扩展点,比如:Filter, InvokerListener, ExportListener, TelnetHandler, StatusChecker等,<br/>
可以同时加载多个实现,此时,可以用自动激活来简化配置,如:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
@Activate // 无条件自动激活
public class XxxFilter implements Filter {
// ...
}]]></script>
</div></div>
<p>或:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
@Activate("xxx") // 当配置了xxx参数,并且参数为有效值时激活,比如配了cache="lru",自动激活CacheFilter。
public class XxxFilter implements Filter {
// ...
}]]></script>
</div></div>
<p>或:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
@Activate(group = "provider", value = "xxx") // 只对提供方激活,group可选"provider"或"consumer"
public class XxxFilter implements Filter {
// ...
}]]></script>
</div></div>
<h2><a name="DeveloperGuide-zh-%E5%AE%9E%E7%8E%B0%E7%BB%86%E8%8A%82"></a>实现细节</h2>
<p>(<a href="Implementation+Detail-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Implementation+Detail-zh" title="Implementation Detail-zh">+</a>) (<a href="#DeveloperGuide-zh-%E5%AE%9E%E7%8E%B0%E7%BB%86%E8%8A%82">#</a>)</p>
<h3><a name="DeveloperGuide-zh-%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%87%E7%A8%8B%E7%BB%86%E8%8A%82"></a>初始化过程细节</h3>
<p>(<a href="Init+Detail-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Init+Detail-zh" title="Init Detail-zh">+</a>) (<a href="#DeveloperGuide-zh-%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%87%E7%A8%8B%E7%BB%86%E8%8A%82">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%E8%A7%A3%E6%9E%90%E6%9C%8D%E5%8A%A1"></a>解析服务</h4>
<ul>
<li>基于dubbo.jar内的META-INF/spring.handlers配置,Spring在遇到dubbo名称空间时,会回调DubboNamespaceHandler。</li>
<li>所有dubbo的标签,都统一用DubboBeanDefinitionParser进行解析,基于一对一属性映射,将XML标签解析为Bean对象。</li>
<li>在ServiceConfig.export()或ReferenceConfig.get()初始化时,将Bean对象转换URL格式,所有Bean属性转成URL的参数。</li>
<li>然后将URL传给<a href="Developer+Guide-zh.htm#DeveloperGuide-zh-%E5%8D%8F%E8%AE%AE%E6%89%A9%E5%B1%95" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh#DeveloperGuide-zh-%E5%8D%8F%E8%AE%AE%E6%89%A9%E5%B1%95">Protocol扩展点</a>,基于扩展点的<a href="Developer+Guide-zh.htm#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E9%80%82%E5%BA%94" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E9%80%82%E5%BA%94">Adaptive机制</a>,根据URL的协议头,进行不同协议的服务暴露或引用。</li>
</ul>
<h4><a name="DeveloperGuide-zh-%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1"></a>暴露服务</h4>
<p><b>(1) 只暴露服务端口:</b></p>
<ul>
<li>在没有注册中心,直接暴露提供者的情况下,即:
<ul>
<li>&lt;dubbo:service regisrty="N/A" /&gt; or &lt;dubbo:registry address="N/A" /&gt;</li>
</ul>
</li>
<li>ServiceConfig解析出的URL的格式为:
<ul>
<li>dubbo://service-host/com.foo.FooService?version=1.0.0</li>
</ul>
</li>
<li>基于扩展点的Adaptive机制,通过URL的"dubbo://"协议头识别,直接调用DubboProtocol的export()方法,打开服务端口。</li>
</ul>
<p><b>(2) 向注册中心暴露服务:</b></p>
<ul>
<li>在有注册中心,需要注册提供者地址的情况下,即:
<ul>
<li>&lt;dubbo:registry address="zookeeper://10.20.153.10:2181" /&gt;</li>
</ul>
</li>
<li>ServiceConfig解析出的URL的格式为:
<ul>
<li>registry://registry-host/com.alibaba.dubbo.registry.RegistryService?export=URL.encode("dubbo://service-host/com.foo.FooService?version=1.0.0")</li>
</ul>
</li>
<li>基于扩展点的Adaptive机制,通过URL的"registry://"协议头识别,就会调用RegistryProtocol的export()方法,将export参数中的提供者URL,先注册到注册中心,再重新传给Protocol扩展点进行暴露:
<ul>
<li>dubbo://service-host/com.foo.FooService?version=1.0.0</li>
</ul>
</li>
<li>基于扩展点的Adaptive机制,通过提供者URL的"dubbo://"协议头识别,就会调用DubboProtocol的export()方法,打开服务端口。</li>
</ul>
<h4><a name="DeveloperGuide-zh-%E5%BC%95%E7%94%A8%E6%9C%8D%E5%8A%A1"></a>引用服务</h4>
<p><b>(1) 直连引用服务:</b></p>
<ul>
<li>在没有注册中心,直连提供者的情况下,即:
<ul>
<li>&lt;dubbo:reference url="dubbo://service-host/com.foo.FooService?version=1.0.0" /&gt;</li>
</ul>
</li>
<li>ReferenceConfig解析出的URL的格式为:
<ul>
<li>dubbo://service-host/com.foo.FooService?version=1.0.0</li>
</ul>
</li>
<li>基于扩展点的Adaptive机制,通过URL的"dubbo://"协议头识别,直接调用DubboProtocol的refer()方法,返回提供者引用。</li>
</ul>
<p><b>(2) 从注册中心发现引用服务:</b></p>
<ul>
<li>在有注册中心,通过注册中心发现提供者地址的情况下,即:
<ul>
<li>&lt;dubbo:registry address="zookeeper://10.20.153.10:2181" /&gt;</li>
</ul>
</li>
<li>ReferenceConfig解析出的URL的格式为:
<ul>
<li>registry://registry-host/com.alibaba.dubbo.registry.RegistryService?refer=URL.encode("consumer://consumer-host/com.foo.FooService?version=1.0.0")</li>
</ul>
</li>
<li>基于扩展点的Adaptive机制,通过URL的"registry://"协议头识别,就会调用RegistryProtocol的refer()方法,基于refer参数中的条件,查询提供者URL,如:
<ul>
<li>dubbo://service-host/com.foo.FooService?version=1.0.0</li>
</ul>
</li>
<li>基于扩展点的Adaptive机制,通过提供者URL的"dubbo://"协议头识别,就会调用DubboProtocol的refer()方法,得到提供者引用。</li>
<li>然后RegistryProtocol将多个提供者引用,通过Cluster扩展点,伪装成单个提供者引用返回。</li>
</ul>
<h4><a name="DeveloperGuide-zh-%E6%8B%A6%E6%88%AA%E6%9C%8D%E5%8A%A1"></a>拦截服务</h4>
<ul>
<li>基于扩展点的<a href="Developer+Guide-zh.htm#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E5%8A%A8%E5%8C%85%E8%A3%85" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E8%87%AA%E5%8A%A8%E5%8C%85%E8%A3%85">Wrapper机制</a>,所有的Protocol扩展点都会自动套上Wrapper类。</li>
<li>基于ProtocolFilterWrapper类,将所有Filter组装成链,在链的最后一节调用真实的引用。</li>
<li>基于ProtocolListenerWrapper类,将所有InvokerListener和ExporterListener组装集合,在暴露和引用前后,进行回调。</li>
<li>包括监控在内,所有附加功能,全部通过Filter拦截实现。</li>
</ul>
<h3><a name="DeveloperGuide-zh-%E8%BF%9C%E7%A8%8B%E8%B0%83%E7%94%A8%E7%BB%86%E8%8A%82"></a>远程调用细节</h3>
<p>(<a href="RPC+Detail-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/RPC+Detail-zh" title="RPC Detail-zh">+</a>) (<a href="#DeveloperGuide-zh-%E8%BF%9C%E7%A8%8B%E8%B0%83%E7%94%A8%E7%BB%86%E8%8A%82">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>作者:</b> 白文志 (来自开源社区)</td></tr></table></div>
<h4><a name="DeveloperGuide-zh-%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%9A%B4%E9%9C%B2%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E7%9A%84%E8%AF%A6%E7%BB%86%E8%BF%87%E7%A8%8B"></a>服务提供者暴露一个服务的详细过程</h4>
<p><span class="image-wrap" style=""><img src="dubbo_rpc_export.jpg-version=1&modificationDate=1335250516000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/7669801/dubbo_rpc_export.jpg?version=1&modificationDate=1335250516000" style="border: 0px solid black" /></span></p>
<p>上图是服务提供者暴露服务的主过程:<br/>
首先ServiceConfig类拿到对外提供服务的实际类ref(如:HelloWorldImpl),然后通过ProxyFactory类的getInvoker方法使用ref生成一个AbstractProxyInvoker实例,到这一步就完成具体服务到Invoker的转化。接下来就是Invoker转换到Exporter的过程。<br/>
Dubbo处理服务暴露的关键就在Invoker转换到Exporter的过程(如上图中的红色部分),下面我们以Dubbo和RMI这两种典型协议的实现来进行说明:</p>
<h5><a name="DeveloperGuide-zh-Dubbo%E7%9A%84%E5%AE%9E%E7%8E%B0"></a>Dubbo的实现</h5>
<p>Dubbo协议的Invoker转为Exporter发生在DubboProtocol类的export方法,它主要是打开socket侦听服务,并接收客户端发来的各种请求,通讯细节由Dubbo自己实现。</p>
<h5><a name="DeveloperGuide-zh-RMI%E7%9A%84%E5%AE%9E%E7%8E%B0"></a>RMI的实现</h5>
<p>RMI协议的Invoker转为Exporter发生在RmiProtocol类的export方法,<br/>
它通过Spring或Dubbo或JDK来实现RMI服务,通讯细节这一块由JDK底层来实现,这就省了不少工作量。</p>
<h4><a name="DeveloperGuide-zh-%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%E6%B6%88%E8%B4%B9%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E7%9A%84%E8%AF%A6%E7%BB%86%E8%BF%87%E7%A8%8B"></a>服务消费者消费一个服务的详细过程</h4>
<p><span class="image-wrap" style=""><img src="dubbo_rpc_refer.jpg-version=1&modificationDate=1335250516000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/7669801/dubbo_rpc_refer.jpg?version=1&modificationDate=1335250516000" style="border: 0px solid black" /></span></p>
<p>上图是服务消费的主过程:<br/>
首先ReferenceConfig类的init方法调用Protocol的refer方法生成Invoker实例(如上图中的红色部分),这是服务消费的关键。接下来把Invoker转换为客户端需要的接口(如:HelloWorld)。<br/>
关于每种协议如RMI/Dubbo/Web service等它们在调用refer方法生成Invoker实例的细节和上一章节所描述的类似。</p>
<h4><a name="DeveloperGuide-zh-%E6%BB%A1%E7%9C%BC%E9%83%BD%E6%98%AFInvoker"></a>满眼都是Invoker</h4>
<p>由于Invoker是Dubbo领域模型中非常重要的一个概念,很多设计思路都是向它靠拢。这就使得Invoker渗透在整个实现代码里,对于刚开始接触Dubbo的人,确实容易给搞混了。<br/>
下面我们用一个精简的图来说明最重要的两种Invoker:服务提供Invoker和服务消费Invoker:</p>
<p><span class="image-wrap" style=""><img src="dubbo_rpc_invoke.jpg-version=1&modificationDate=1335250516000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/7669801/dubbo_rpc_invoke.jpg?version=1&modificationDate=1335250516000" style="border: 0px solid black" /></span></p>
<p>为了更好的解释上面这张图,我们结合服务消费和提供者的代码示例来进行说明:</p>
<h5><a name="DeveloperGuide-zh-%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85%E4%BB%A3%E7%A0%81"></a>服务消费者代码</h5>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public class DemoClientAction {
private DemoService demoService;
public void setDemoService(DemoService demoService) {
this.demoService = demoService;
}
public void start() {
String hello = demoService.sayHello("world" + i);
}
}]]></script>
</div></div>
<p>上面代码中的’DemoService’就是上图中服务消费端的proxy,用户代码通过这个proxy调用其对应的Invoker(DubboInvoker、 HessianRpcInvoker、 InjvmInvoker、 RmiInvoker、 WebServiceInvoker中的任何一个),而该Invoker实现了真正的远程服务调用。</p>
<h5><a name="DeveloperGuide-zh-%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E4%BB%A3%E7%A0%81"></a>服务提供者代码</h5>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public class DemoServiceImpl implements DemoService {
public String sayHello(String name) throws RemoteException {
return "Hello " + name;
}
}]]></script>
</div></div>
<p>上面这个类会被封装成为一个AbstractProxyInvoker实例,并新生成一个<br/>
Exporter实例。这样当网络通讯层收到一个请求后,会找到对应的Exporter实例,并调用它所对应的AbstractProxyInvoker实例,从而真正调用了服务提供者的代码。<br/>
Dubbo里还有一些其他的Invoker类,但上面两种是最重要的。</p>
<h3><a name="DeveloperGuide-zh-%E8%BF%9C%E7%A8%8B%E9%80%9A%E8%AE%AF%E7%BB%86%E8%8A%82"></a>远程通讯细节</h3>
<p>(<a href="Remoting+Detail-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Remoting+Detail-zh" title="Remoting Detail-zh">+</a>) (<a href="#DeveloperGuide-zh-%E8%BF%9C%E7%A8%8B%E9%80%9A%E8%AE%AF%E7%BB%86%E8%8A%82">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%E5%8D%8F%E8%AE%AE%E5%A4%B4%E7%BA%A6%E5%AE%9A"></a>协议头约定</h4>
<p><span class="image-wrap" style=""><img src="dubbo_protocol_header.jpg-version=1&modificationDate=1335251744000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/7669814/dubbo_protocol_header.jpg?version=1&modificationDate=1335251744000" style="border: 0px solid black" /></span></p>
<h4><a name="DeveloperGuide-zh-%E7%BA%BF%E7%A8%8B%E6%B4%BE%E5%8F%91%E6%A8%A1%E5%9E%8B"></a>线程派发模型</h4>
<p><span class="image-wrap" style=""><img src="dubbo-protocol.jpg-version=1&modificationDate=1331068241000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6949458/dubbo-protocol.jpg?version=1&modificationDate=1331068241000" style="border: 0px solid black" /></span></p>
<ul>
<li>Dispather
<ul>
<li>all, direct, message, execution, connection</li>
</ul>
</li>
<li>ThreadPool
<ul>
<li>fixed, cached</li>
</ul>
</li>
</ul>
<h2><a name="DeveloperGuide-zh-SPI%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C"></a>SPI参考手册</h2>
<p>(<a href="SPI+Reference-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/SPI+Reference-zh" title="SPI Reference-zh">+</a>) (<a href="#DeveloperGuide-zh-SPI%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C">#</a>)</p>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>SPI使用范围</b><br />扩展接口仅用于系统集成,或Contributor扩展功能插件。</td></tr></table></div>
<h3><a name="DeveloperGuide-zh-%E5%8D%8F%E8%AE%AE%E6%89%A9%E5%B1%95"></a>协议扩展</h3>
<p>(<a href="Protocol+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Protocol+SPI-zh" title="Protocol SPI-zh">+</a>) (<span class="error">&#91;#&#93;</span>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>RPC协议扩展,封装远程调用细节。</p>
<p>契约:</p>
<ul>
<li>当用户调用refer()所返回的Invoker对象的invoke()方法时,协议需相应执行同URL远端export()传入的Invoker对象的invoke()方法。</li>
<li>其中,refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求,export()传入的Invoker由框架实现并传入,协议不需要关心。</li>
</ul>
<p>注意:</p>
<ul>
<li>协议不关心业务接口的透明代理,以Invoker为中心,由外层将Invoker转换为业务接口。</li>
<li>协议不一定要是TCP网络通讯,比如通过共享文件,IPC进程间通讯等。</li>
</ul>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.Protocol
com.alibaba.dubbo.rpc.Exporter
com.alibaba.dubbo.rpc.Invoker]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public interface Protocol {
/**
* 暴露远程服务:&lt;br&gt;
* 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();&lt;br&gt;
* 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。&lt;br&gt;
* 3. export()传入的Invoker由框架实现并传入,协议不需要关心。&lt;br&gt;
*
* @param &lt;T&gt; 服务的类型
* @param invoker 服务的执行体
* @return exporter 暴露服务的引用,用于取消暴露
* @throws RpcException 当暴露服务出错时抛出,比如端口已占用
*/
&lt;T&gt; Exporter&lt;T&gt; export(Invoker&lt;T&gt; invoker) throws RpcException;
/**
* 引用远程服务:&lt;br&gt;
* 1. 当用户调用refer()所返回的Invoker对象的invoke()方法时,协议需相应执行同URL远端export()传入的Invoker对象的invoke()方法。&lt;br&gt;
* 2. refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求。&lt;br&gt;
* 3. 当url中有设置check=false时,连接失败不能抛出异常,需内部自动恢复。&lt;br&gt;
*
* @param &lt;T&gt; 服务的类型
* @param type 服务的类型
* @param url 远程服务的URL地址
* @return invoker 服务的本地代理
* @throws RpcException 当连接服务提供方失败时抛出
*/
&lt;T&gt; Invoker&lt;T&gt; refer(Class&lt;T&gt; type, URL url) throws RpcException;
}]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol id="xxx1" name="xxx" /&gt; &lt;!-- 声明协议,如果没有配置id,将以nameid --&gt;
&lt;dubbo:service protocol="xxx1" /&gt; &lt;!-- 引用协议,如果没有配置protocol属性,将在ApplicationContext中自动扫描protocol配置 --&gt;
&lt;dubbo:provider protocol="xxx1" /&gt; &lt;!-- 引用协议缺省值,当&lt;dubbo:service&gt;没有配置prototol属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.injvm.InjvmProtocol
com.alibaba.dubbo.rpc.dubbo.DubboProtocol
com.alibaba.dubbo.rpc.rmi.RmiProtocol
com.alibaba.dubbo.rpc.http.HttpProtocol
com.alibaba.dubbo.rpc.http.hessian.HessianProtocol]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxProtocol.java (实现Protocol接口)
|-XxxExporter.java (实现Exporter接口)
|-XxxInvoker.java (实现Invoker接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.rpc.Protocol (纯文本文件,内容为:xxx=com.xxx.XxxProtocol)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxProtocol.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.Protocol;
public class XxxProtocol implements Protocol {
public &lt;T&gt; Exporter&lt;T&gt; export(Invoker&lt;T&gt; invoker) throws RpcException {
return new XxxExporter(invoker);
}
public &lt;T&gt; Invoker&lt;T&gt; refer(Class&lt;T&gt; type, URL url) throws RpcException {
return new XxxInvoker(type, url);
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxExporter.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.support.AbstractExporter;
public class XxxExporter&lt;T&gt; extends AbstractExporter&lt;T&gt; {
public XxxExporter(Invoker&lt;T&gt; invoker) throws RemotingException{
super(invoker);
// ...
}
public void unexport() {
super.unexport();
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxInvoker.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.support.AbstractInvoker;
public class XxxInvoker&lt;T&gt; extends AbstractInvoker&lt;T&gt; {
public XxxInvoker(Class&lt;T&gt; type, URL url) throws RemotingException{
super(type, url);
}
protected abstract Object doInvoke(Invocation invocation) throws Throwable {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.rpc.Protocol</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxProtocol]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E8%B0%83%E7%94%A8%E6%8B%A6%E6%88%AA%E6%89%A9%E5%B1%95"></a>调用拦截扩展</h3>
<p>(<a href="Filter+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Filter+SPI-zh" title="Filter SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E8%B0%83%E7%94%A8%E6%8B%A6%E6%88%AA%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E"></a>(1) 扩展说明</h4>
<p>服务提供方和服务消费方调用过程拦截,Dubbo本身的大多功能均基于此扩展点实现,每次远程方法执行,该拦截都会被执行,请注意对性能的影响。<br/>
约定:</p>
<ul>
<li>用户自定义filter默认在内置filter之后。</li>
<li>特殊值default,表示缺省扩展点插入的位置。
<ul>
<li>比如:filter="xxx,default,yyy",表示xxx在缺省filter之前,yyy在缺省filter之后。</li>
</ul>
</li>
<li>特殊符号-,表示剔除。
<ul>
<li>比如:filter="-foo1",剔除添加缺省扩展点foo1。</li>
<li>比如:filter="-default",剔除添加所有缺省扩展点。</li>
</ul>
</li>
<li>provider和service同时配置的filter时,累加所有filter,而不是覆盖。
<ul>
<li>比如:&lt;dubbo:provider filter="xxx,yyy"/&gt;和&lt;dubbo:service filter="aaa,bbb" /&gt;,则xxx,yyy,aaa,bbb均会生效。</li>
<li>如果要覆盖,需配置:&lt;dubbo:service filter="-xxx,-yyy,aaa,bbb" /&gt;</li>
</ul>
</li>
</ul>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.Filter]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference filter="xxx,yyy" /&gt; &lt;!-- 消费方调用过程拦截 --&gt;
&lt;dubbo:consumer filter="xxx,yyy"/&gt; &lt;!-- 消费方调用过程缺省拦截器,将拦截所有reference --&gt;
&lt;dubbo:service filter="xxx,yyy" /&gt; &lt;!-- 提供方调用过程拦截 --&gt;
&lt;dubbo:provider filter="xxx,yyy"/&gt; &lt;!-- 提供方调用过程缺省拦截器,将拦截所有service --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.filter.EchoFilter
com.alibaba.dubbo.rpc.filter.GenericFilter
com.alibaba.dubbo.rpc.filter.GenericImplFilter
com.alibaba.dubbo.rpc.filter.TokenFilter
com.alibaba.dubbo.rpc.filter.AccessLogFilter
com.alibaba.dubbo.rpc.filter.CountFilter
com.alibaba.dubbo.rpc.filter.ActiveLimitFilter
com.alibaba.dubbo.rpc.filter.ClassLoaderFilter
com.alibaba.dubbo.rpc.filter.ContextFilter
com.alibaba.dubbo.rpc.filter.ConsumerContextFilter
com.alibaba.dubbo.rpc.filter.ExceptionFilter
com.alibaba.dubbo.rpc.filter.ExecuteLimitFilter
com.alibaba.dubbo.rpc.filter.DeprecatedFilter]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxFilter.java (实现Filter接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.rpc.Filter (纯文本文件,内容为:xxx=com.xxx.XxxFilter)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxFilter.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
public class XxxFilter implements Filter {
public Result invoke(Invoker&lt;?&gt; invoker, Invocation invocation) throws RpcException {
// before filter ...
Result result = invoker.invoke(invocation);
// after filter ...
return result;
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.rpc.Filter</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxFilter]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E5%BC%95%E7%94%A8%E7%9B%91%E5%90%AC%E6%89%A9%E5%B1%95"></a>引用监听扩展</h3>
<p>(<a href="InvokerListener+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/InvokerListener+SPI-zh" title="InvokerListener SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E5%BC%95%E7%94%A8%E7%9B%91%E5%90%AC%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>当有服务引用时,触发该事件。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.InvokerListener]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference listener="xxx,yyy" /&gt; &lt;!-- 引用服务监听 --&gt;
&lt;dubbo:consumer listener="xxx,yyy" /&gt; &lt;!-- 引用服务缺省监听器 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.listener.DeprecatedInvokerListener]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxInvokerListener.java (实现InvokerListener接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.rpc.InvokerListener (纯文本文件,内容为:xxx=com.xxx.XxxInvokerListener)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxInvokerListener.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.InvokerListener;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.RpcException;
public class XxxInvokerListener implements InvokerListener {
public void referred(Invoker&lt;?&gt; invoker) throws RpcException {
// ...
}
public void destroyed(Invoker&lt;?&gt; invoker) throws RpcException {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.rpc.InvokerListener</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxInvokerListener]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E6%9A%B4%E9%9C%B2%E7%9B%91%E5%90%AC%E6%89%A9%E5%B1%95"></a>暴露监听扩展</h3>
<p>(<a href="ExporterListener+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/ExporterListener+SPI-zh" title="ExporterListener SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E6%9A%B4%E9%9C%B2%E7%9B%91%E5%90%AC%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>当有服务暴露时,触发该事件。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.ExporterListener]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service listener="xxx,yyy" /&gt; &lt;!-- 暴露服务监听 --&gt;
&lt;dubbo:provider listener="xxx,yyy" /&gt; &lt;!-- 暴露服务缺省监听器 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.registry.directory.RegistryExporterListener]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxExporterListener.java (实现ExporterListener接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.rpc.ExporterListener (纯文本文件,内容为:xxx=com.xxx.XxxExporterListener)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxExporterListener.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.ExporterListener;
import com.alibaba.dubbo.rpc.Exporter;
import com.alibaba.dubbo.rpc.RpcException;
public class XxxExporterListener implements ExporterListener {
public void exported(Exporter&lt;?&gt; exporter) throws RpcException {
// ...
}
public void unexported(Exporter&lt;?&gt; exporter) throws RpcException {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.rpc.ExporterListener</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxExporterListener]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E9%9B%86%E7%BE%A4%E6%89%A9%E5%B1%95"></a>集群扩展</h3>
<p>(<a href="Cluster+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Cluster+SPI-zh" title="Cluster SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E9%9B%86%E7%BE%A4%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>当有多个服务提供方时,将多个服务提供方组织成一个集群,并伪装成一个提供方。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.cluster.Cluster]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol cluster="xxx" /&gt;
&lt;dubbo:provider cluster="xxx" /&gt; &lt;!-- 缺省值配置,如果&lt;dubbo:protocol&gt;没有配置cluster时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.cluster.support.FailoverCluster
com.alibaba.dubbo.rpc.cluster.support.FailfastCluster
com.alibaba.dubbo.rpc.cluster.support.FailsafeCluster
com.alibaba.dubbo.rpc.cluster.support.FailbackCluster
com.alibaba.dubbo.rpc.cluster.support.ForkingCluster
com.alibaba.dubbo.rpc.cluster.support.AvailableCluster]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxCluster.java (实现Cluster接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.rpc.cluster.Cluster (纯文本文件,内容为:xxx=com.xxx.XxxCluster)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxCluster.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.cluster.Cluster;
import com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker;
import com.alibaba.dubbo.rpc.cluster.Directory;
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
public class XxxCluster implements Cluster {
public &lt;T&gt; Invoker&lt;T&gt; merge(Directory&lt;T&gt; directory) throws RpcException {
return new AbstractClusterInvoker&lt;T&gt;(directory) {
public Result doInvoke(Invocation invocation, List&lt;Invoker&lt;T&gt;&gt; invokers, LoadBalance loadbalance) throws RpcException {
// ...
}
};
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.rpc.cluster.Cluster</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxCluster]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E8%B7%AF%E7%94%B1%E6%89%A9%E5%B1%95"></a>路由扩展</h3>
<p>(<a href="RouterFactory+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/RouterFactory+SPI-zh" title="RouterFactory SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E8%B7%AF%E7%94%B1%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>从多个服务提者方中选择一个进行调用。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.cluster.RouterFactory
com.alibaba.dubbo.rpc.cluster.Router]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol router="xxx" /&gt;
&lt;dubbo:provider router="xxx" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置loadbalance时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.cluster.router.ScriptRouterFactory
com.alibaba.dubbo.rpc.cluster.router.FileRouterFactory]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxRouterFactory.java (实现LoadBalance接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.rpc.cluster.RouterFactory (纯文本文件,内容为:xxx=com.xxx.XxxRouterFactory)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxRouterFactory.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.cluster.RouterFactory;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.RpcException;
public class XxxRouterFactory implements RouterFactory {
public &lt;T&gt; List&lt;Invoker&lt;T&gt;&gt; select(List&lt;Invoker&lt;T&gt;&gt; invokers, Invocation invocation) throws RpcException {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.rpc.cluster.RouterFactory</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxRouterFactory]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%89%A9%E5%B1%95"></a>负载均衡扩展</h3>
<p>(<a href="LoadBalance+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/LoadBalance+SPI-zh" title="LoadBalance SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>从多个服务提者方中选择一个进行调用。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.cluster.LoadBalance]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol loadbalance="xxx" /&gt;
&lt;dubbo:provider loadbalance="xxx" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置loadbalance时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance
com.alibaba.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance
com.alibaba.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxLoadBalance.java (实现LoadBalance接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.rpc.cluster.LoadBalance (纯文本文件,内容为:xxx=com.xxx.XxxLoadBalance)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxLoadBalance.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.RpcException;
public class XxxLoadBalance implements LoadBalance {
public &lt;T&gt; Invoker&lt;T&gt; select(List&lt;Invoker&lt;T&gt;&gt; invokers, Invocation invocation) throws RpcException {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.rpc.cluster.LoadBalance</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxLoadBalance]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E5%90%88%E5%B9%B6%E7%BB%93%E6%9E%9C%E6%89%A9%E5%B1%95"></a>合并结果扩展</h3>
<p>(<a href="Merger+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Merger+SPI-zh" title="Merger SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E5%90%88%E5%B9%B6%E7%BB%93%E6%9E%9C%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>合并返回结果,用于分组聚合。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.cluster.Merger]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:method merger="xxx" /&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.cluster.merger.ArrayMerger
com.alibaba.dubbo.rpc.cluster.merger.ListMerger
com.alibaba.dubbo.rpc.cluster.merger.SetMerger
com.alibaba.dubbo.rpc.cluster.merger.MapMerger]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxMerger.java (实现Merger接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.rpc.cluster.Merger (纯文本文件,内容为:xxx=com.xxx.XxxMerger)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxMerger.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.cluster.Merger;
public class XxxMerger&lt;T&gt; implements Merger&lt;T&gt; {
public T merge(T... results) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.rpc.cluster.Merger</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxMerger]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%89%A9%E5%B1%95"></a>注册中心扩展</h3>
<p>(<a href="RegistryFactory+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/RegistryFactory+SPI-zh" title="RegistryFactory SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>负责服务的注册与发现。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.registry.RegistryFactory
com.alibaba.dubbo.registry.Registry]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:registry id="xxx1" address="xxx://ip:port" /&gt; &lt;!-- 定义注册中心 --&gt;
&lt;dubbo:service registry="xxx1" /&gt; &lt;!-- 引用注册中心,如果没有配置registry属性,将在ApplicationContext中自动扫描registry配置 --&gt;
&lt;dubbo:provider registry="xxx1" /&gt; &lt;!-- 引用注册中心缺省值,当&lt;dubbo:service&gt;没有配置registry属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E6%89%A9%E5%B1%95%E5%A5%91%E7%BA%A6%EF%BC%9A"></a>(4) 扩展契约:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>RegistryFactory.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public interface RegistryFactory {
/**
* 连接注册中心.
*
* 连接注册中心需处理契约:&lt;br&gt;
* 1. 当设置check=false时表示不检查连接,否则在连接不上时抛出异常。&lt;br&gt;
* 2. 支持URL上的username:password权限认证。&lt;br&gt;
* 3. 支持backup=10.20.153.10备选注册中心集群地址。&lt;br&gt;
* 4. 支持file=registry.cache本地磁盘文件缓存。&lt;br&gt;
* 5. 支持timeout=1000请求超时设置。&lt;br&gt;
* 6. 支持session=60000会话超时或过期设置。&lt;br&gt;
*
* @param url 注册中心地址,不允许为空
* @return 注册中心引用,总不返回空
*/
Registry getRegistry(URL url);
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>RegistryService.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public interface RegistryService { // Registry extends RegistryService
/**
* 注册服务.
*
* 注册需处理契约:&lt;br&gt;
* 1. 当URL设置了check=false时,注册失败后不报错,在后台定时重试,否则抛出异常。&lt;br&gt;
* 2. 当URL设置了dynamic=false参数,则需持久存储,否则,当注册者出现断电等情况异常退出时,需自动删除。&lt;br&gt;
* 3. 当URL设置了category=overrides时,表示分类存储,缺省类别为providers,可按分类部分通知数据。&lt;br&gt;
* 4. 当注册中心重启,网络抖动,不能丢失数据,包括断线自动删除数据。&lt;br&gt;
* 5. 允许URI相同但参数不同的URL并存,不能覆盖。&lt;br&gt;
*
* @param url 注册信息,不允许为空,如:dubbo://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&amp;application=kylin
*/
void register(URL url);
/**
* 取消注册服务.
*
* 取消注册需处理契约:&lt;br&gt;
* 1. 如果是dynamic=false的持久存储数据,找不到注册数据,则抛IllegalStateException,否则忽略。&lt;br&gt;
* 2. 按全URL匹配取消注册。&lt;br&gt;
*
* @param url 注册信息,不允许为空,如:dubbo://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&amp;application=kylin
*/
void unregister(URL url);
/**
* 订阅服务.
*
* 订阅需处理契约:&lt;br&gt;
* 1. 当URL设置了check=false时,订阅失败后不报错,在后台定时重试。&lt;br&gt;
* 2. 当URL设置了category=overrides,只通知指定分类的数据,多个分类用逗号分隔,并允许星号通配,表示订阅所有分类数据。&lt;br&gt;
* 3. 允许以interface,group,version,classifier作为条件查询,如:interface=com.alibaba.foo.BarService&amp;version=1.0.0&lt;br&gt;
* 4. 并且查询条件允许星号通配,订阅所有接口的所有分组的所有版本,或:interface=*&amp;group=*&amp;version=*&amp;classifier=*&lt;br&gt;
* 5. 当注册中心重启,网络抖动,需自动恢复订阅请求。&lt;br&gt;
* 6. 允许URI相同但参数不同的URL并存,不能覆盖。&lt;br&gt;
* 7. 必须阻塞订阅过程,等第一次通知完后再返回。&lt;br&gt;
*
* @param url 订阅条件,不允许为空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&amp;application=kylin
* @param listener 变更事件监听器,不允许为空
*/
void subscribe(URL url, NotifyListener listener);
/**
* 取消订阅服务.
*
* 取消订阅需处理契约:&lt;br&gt;
* 1. 如果没有订阅,直接忽略。&lt;br&gt;
* 2. 按全URL匹配取消订阅。&lt;br&gt;
*
* @param url 订阅条件,不允许为空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&amp;application=kylin
* @param listener 变更事件监听器,不允许为空
*/
void unsubscribe(URL url, NotifyListener listener);
/**
* 查询注册列表,与订阅的推模式相对应,这里为拉模式,只返回一次结果。
*
* @see com.alibaba.dubbo.registry.NotifyListener#notify(List)
* @param url 查询条件,不允许为空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&amp;application=kylin
* @return 已注册信息列表,可能为空,含义同{@link com.alibaba.dubbo.registry.NotifyListener#notify(List&lt;URL&gt;)}的参数。
*/
List&lt;URL&gt; lookup(URL url);
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>NotifyListener.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public interface NotifyListener {
/**
* 当收到服务变更通知时触发。
*
* 通知需处理契约:&lt;br&gt;
* 1. 总是以服务接口和数据类型为维度全量通知,即不会通知一个服务的同类型的部分数据,用户不需要对比上一次通知结果。&lt;br&gt;
* 2. 订阅时的第一次通知,必须是一个服务的所有类型数据的全量通知。&lt;br&gt;
* 3. 中途变更时,允许不同类型的数据分开通知,比如:providers, consumers, routes, overrides,允许只通知其中一种类型,但该类型的数据必须是全量的,不是增量的。&lt;br&gt;
* 4. 如果一种类型的数据为空,需通知一个empty协议并带category参数的标识性URL数据。&lt;br&gt;
* 5. 通知者(即注册中心实现)需保证通知的顺序,比如:单线程推送,队列串行化,带版本对比。&lt;br&gt;
*
* @param urls 已注册信息列表,总不为空,含义同{@link com.alibaba.dubbo.registry.RegistryService#lookup(URL)}的返回值。
*/
void notify(List&lt;URL&gt; urls);
}]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(5) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.registry.support.dubbo.DubboRegistryFactory]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%286%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(6) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxRegistryFactoryjava (实现RegistryFactory接口)
|-XxxRegistry.java (实现Registry接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.registry.RegistryFactory (纯文本文件,内容为:xxx=com.xxx.XxxRegistryFactory)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxRegistryFactory.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.registry.RegistryFactory;
import com.alibaba.dubbo.registry.Registry;
import com.alibaba.dubbo.common.URL;
public class XxxRegistryFactory implements RegistryFactory {
public Registry getRegistry(URL url) {
return new XxxRegistry(url);
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxRegistry.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.registry.Registry;
import com.alibaba.dubbo.registry.NotifyListener;
import com.alibaba.dubbo.common.URL;
public class XxxRegistry implements Registry {
public void register(URL url) {
// ...
}
public void unregister(URL url) {
// ...
}
public void subscribe(URL url, NotifyListener listener) {
// ...
}
public void unsubscribe(URL url, NotifyListener listener) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.registry.RegistryFactory</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxRegistryFactory]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E7%9B%91%E6%8E%A7%E4%B8%AD%E5%BF%83%E6%89%A9%E5%B1%95"></a>监控中心扩展</h3>
<p>(<a href="MonitorFactory+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/MonitorFactory+SPI-zh" title="MonitorFactory SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E7%9B%91%E6%8E%A7%E4%B8%AD%E5%BF%83%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>负责服务调用次和调用时间的监控。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.monitor.MonitorFactory
com.alibaba.dubbo.monitor.Monitor]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:monitor address="xxx://ip:port" /&gt; &lt;!-- 定义监控中心 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.monitor.support.dubbo.DubboMonitorFactory]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxMonitorFactoryjava (实现MonitorFactory接口)
|-XxxMonitor.java (实现Monitor接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.monitor.MonitorFactory (纯文本文件,内容为:xxx=com.xxx.XxxMonitorFactory)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxMonitorFactory.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.monitor.MonitorFactory;
import com.alibaba.dubbo.monitor.Monitor;
import com.alibaba.dubbo.common.URL;
public class XxxMonitorFactory implements MonitorFactory {
public Monitor getMonitor(URL url) {
return new XxxMonitor(url);
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxMonitor.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.monitor.Monitor;
public class XxxMonitor implements Monitor {
public void count(URL statistics) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.monitor.MonitorFactory</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxMonitorFactory]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E5%8A%A0%E8%BD%BD%E6%89%A9%E5%B1%95"></a>扩展点加载扩展</h3>
<p>(<a href="ExtensionFactory+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/ExtensionFactory+SPI-zh" title="ExtensionFactory SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E5%8A%A0%E8%BD%BD%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>扩展点本身的加载容器,可从不同容器加载扩展点。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.extension.ExtensionFactory]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:application compiler="jdk" /&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxExtensionFactory.java (实现ExtensionFactory接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.common.extension.ExtensionFactory (纯文本文件,内容为:xxx=com.xxx.XxxExtensionFactory)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxExtensionFactory.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.common.extension.ExtensionFactory;
public class XxxExtensionFactory implements ExtensionFactory {
public Object getExtension(Class&lt;?&gt; type, String name) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.common.extension.ExtensionFactory</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxExtensionFactory]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E6%89%A9%E5%B1%95"></a>动态代理扩展</h3>
<p>(<a href="ProxyFactory+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/ProxyFactory+SPI-zh" title="ProxyFactory SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>将Invoker接口转换成业务接口。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.ProxyFactory]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol proxy="xxx" /&gt;
&lt;dubbo:provider proxy="xxx" /&gt; &lt;!-- 缺省值配置,当&lt;dubbo:protocol&gt;没有配置proxy属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.rpc.proxy.JdkProxyFactory
com.alibaba.dubbo.rpc.proxy.JavassistProxyFactory]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxProxyFactory.java (实现ProxyFactory接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.rpc.ProxyFactory (纯文本文件,内容为:xxx=com.xxx.XxxProxyFactory)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxProxyFactory.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.rpc.ProxyFactory;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.RpcException;
public class XxxProxyFactory implements ProxyFactory {
public &lt;T&gt; T getProxy(Invoker&lt;T&gt; invoker) throws RpcException {
// ...
}
public &lt;T&gt; Invoker&lt;T&gt; getInvoker(T proxy, Class&lt;T&gt; type, URL url) throws RpcException {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.rpc.ProxyFactory</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxProxyFactory]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E7%BC%96%E8%AF%91%E5%99%A8%E6%89%A9%E5%B1%95"></a>编译器扩展</h3>
<p>(<a href="Compiler+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Compiler+SPI-zh" title="Compiler SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E7%BC%96%E8%AF%91%E5%99%A8%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>Java代码编译器,用于动态生成字节码,加速调用。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.compiler.Compiler]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<p>自动加载</p>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.compiler.support.JdkCompiler
com.alibaba.dubbo.common.compiler.support.JavassistCompiler]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxCompiler.java (实现Compiler接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.common.compiler.Compiler (纯文本文件,内容为:xxx=com.xxx.XxxCompiler)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxCompiler.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.common.compiler.Compiler;
public class XxxCompiler implements Compiler {
public Object getExtension(Class&lt;?&gt; type, String name) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.common.compiler.Compiler</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxCompiler]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E6%B6%88%E6%81%AF%E6%B4%BE%E5%8F%91%E6%89%A9%E5%B1%95"></a>消息派发扩展</h3>
<p>(<a href="Dispatcher+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Dispatcher+SPI-zh" title="Dispatcher SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E6%B6%88%E6%81%AF%E6%B4%BE%E5%8F%91%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>通道信息派发器,用于指定线程池模型。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.remoting.Dispatcher]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol dispatcher="xxx" /&gt;
&lt;dubbo:provider dispatcher="xxx" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置dispatcher属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.remoting.transport.dispatcher.all.AllDispatcher
com.alibaba.dubbo.remoting.transport.dispatcher.direct.DirectDispatcher
com.alibaba.dubbo.remoting.transport.dispatcher.message.MessageOnlyDispatcher
com.alibaba.dubbo.remoting.transport.dispatcher.execution.ExecutionDispatcher
com.alibaba.dubbo.remoting.transport.dispatcher.connection.ConnectionOrderedDispatcher]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxDispatcher.java (实现Dispatcher接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.remoting.Dispatcher (纯文本文件,内容为:xxx=com.xxx.XxxDispatcher)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxDispatcher.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.remoting.Dispatcher;
public class XxxDispatcher implements Dispatcher {
public Group lookup(URL url) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.remoting.Dispatcher</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxDispatcher]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%89%A9%E5%B1%95"></a>线程池扩展</h3>
<p>(<a href="ThreadPool+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/ThreadPool+SPI-zh" title="ThreadPool SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>服务提供方线程程实现策略,当服务器收到一个请求时,需要在线程池中创建一个线程去执行服务提供方业务逻辑。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.threadpool.ThreadPool]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol threadpool="xxx" /&gt;
&lt;dubbo:provider threadpool="xxx" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置threadpool时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.threadpool.FixedThreadPool
com.alibaba.dubbo.common.threadpool.CachedThreadPool]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxThreadPool.java (实现ThreadPool接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.common.threadpool.ThreadPool (纯文本文件,内容为:xxx=com.xxx.XxxThreadPool)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxThreadPool.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.common.threadpool.ThreadPool;
import java.util.concurrent.Executor;
public class XxxThreadPool implements ThreadPool {
public Executor getExecutor() {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.common.threadpool.ThreadPool</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxThreadPool]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E5%BA%8F%E5%88%97%E5%8C%96%E6%89%A9%E5%B1%95"></a>序列化扩展</h3>
<p>(<a href="Serialization+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Serialization+SPI-zh" title="Serialization SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E5%BA%8F%E5%88%97%E5%8C%96%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>将对象转成字节流,用于网络传输,以及将字节流转为对象,用于在收到字节流数据后还原成对象。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.serialize.Serialization
com.alibaba.dubbo.common.serialize.ObjectInput
com.alibaba.dubbo.common.serialize.ObjectOutput]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol serialization="xxx" /&gt; &lt;!-- 协议的序列化方式 --&gt;
&lt;dubbo:provider serialization="xxx" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置serialization时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.serialize.dubbo.DubboSerialization
com.alibaba.dubbo.common.serialize.hessian.Hessian2Serialization
com.alibaba.dubbo.common.serialize.java.JavaSerialization
com.alibaba.dubbo.common.serialize.java.CompactedJavaSerialization]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxSerialization.java (实现Serialization接口)
|-XxxObjectInput.java (实现ObjectInput接口)
|-XxxObjectOutput.java (实现ObjectOutput接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.common.serialize.Serialization (纯文本文件,内容为:xxx=com.xxx.XxxSerialization)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxSerialization.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.common.serialize.Serialization;
import com.alibaba.dubbo.common.serialize.ObjectInput;
import com.alibaba.dubbo.common.serialize.ObjectOutput;
public class XxxSerialization implements Serialization {
public ObjectOutput serialize(Parameters parameters, OutputStream output) throws IOException {
return new XxxObjectOutput(output);
}
public ObjectInput deserialize(Parameters parameters, InputStream input) throws IOException {
return new XxxObjectInput(input);
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.common.serialize.Serialization</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxSerialization]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E7%BD%91%E7%BB%9C%E4%BC%A0%E8%BE%93%E6%89%A9%E5%B1%95"></a>网络传输扩展</h3>
<p>(<a href="Transporter+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Transporter+SPI-zh" title="Transporter SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E7%BD%91%E7%BB%9C%E4%BC%A0%E8%BE%93%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>远程通讯的服务器及客户端传输实现。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.remoting.Transporter
com.alibaba.dubbo.remoting.Server
com.alibaba.dubbo.remoting.Client]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol transporter="xxx" /&gt; &lt;!-- 服务器和客户端使用相同的传输实现 --&gt;
&lt;dubbo:protocol server="xxx" client="xxx" /&gt; &lt;!-- 服务器和客户端使用不同的传输实现 --&gt;
&lt;dubbo:provider transporter="xxx" server="xxx" client="xxx" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置transporter/server/client属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.remoting.transport.transporter.netty.NettyTransporter
com.alibaba.dubbo.remoting.transport.transporter.mina.MinaTransporter
com.alibaba.dubbo.remoting.transport.transporter.grizzly.GrizzlyTransporter]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxTransporter.java (实现Transporter接口)
|-XxxServer.java (实现Server接口)
|-XxxClient.java (实现Client接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.remoting.Transporter (纯文本文件,内容为:xxx=com.xxx.XxxTransporter)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxTransporter.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.remoting.Transporter;
public class XxxTransporter implements Transporter {
public Server bind(URL url, ChannelHandler handler) throws RemotingException {
return new XxxServer(url, handler);
}
public Client connect(URL url, ChannelHandler handler) throws RemotingException {
return new XxxClient(url, handler);
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxServer.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.remoting.transport.transporter.AbstractServer;
public class XxxServer extends AbstractServer {
public XxxServer(URL url, ChannelHandler handler) throws RemotingException{
super(url, handler);
}
protected void doOpen() throws Throwable {
// ...
}
protected void doClose() throws Throwable {
// ...
}
public Collection&lt;Channel&gt; getChannels() {
// ...
}
public Channel getChannel(InetSocketAddress remoteAddress) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxClient.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.remoting.transport.transporter.AbstractClient;
public class XxxClient extends AbstractClient {
public XxxServer(URL url, ChannelHandler handler) throws RemotingException{
super(url, handler);
}
protected void doOpen() throws Throwable {
// ...
}
protected void doClose() throws Throwable {
// ...
}
protected void doConnect() throws Throwable {
// ...
}
public Channel getChannel() {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.remoting.Transporter</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxTransporter]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E4%BF%A1%E6%81%AF%E4%BA%A4%E6%8D%A2%E6%89%A9%E5%B1%95"></a>信息交换扩展</h3>
<p>(<a href="Exchanger+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Exchanger+SPI-zh" title="Exchanger SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E4%BF%A1%E6%81%AF%E4%BA%A4%E6%8D%A2%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>基于传输层之上,实现Request-Response信息交换语义。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.remoting.exchange.Exchanger
com.alibaba.dubbo.remoting.exchange.ExchangeServer
com.alibaba.dubbo.remoting.exchange.ExchangeClient]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol exchanger="xxx" /&gt;
&lt;dubbo:provider exchanger="xxx" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置exchanger属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.remoting.exchange.exchanger.HeaderExchanger]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxExchanger.java (实现Exchanger接口)
|-XxxExchangeServer.java (实现ExchangeServer接口)
|-XxxExchangeClient.java (实现ExchangeClient接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.remoting.exchange.Exchanger (纯文本文件,内容为:xxx=com.xxx.XxxExchanger)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxExchanger.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.remoting.exchange.Exchanger;
public class XxxExchanger implements Exchanger {
public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
return new XxxExchangeServer(url, handler);
}
public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
return new XxxExchangeClient(url, handler);
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxExchangeServer.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.remoting.exchange.ExchangeServer;
public class XxxExchangeServer impelements ExchangeServer {
// ...
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxExchangeClient.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.remoting.exchange.ExchangeClient;
public class XxxExchangeClient impelments ExchangeClient {
// ...
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.remoting.exchange.Exchanger</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxExchanger]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E7%BB%84%E7%BD%91%E6%89%A9%E5%B1%95"></a>组网扩展</h3>
<p>(<a href="Networker+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Networker+SPI-zh" title="Networker SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E7%BB%84%E7%BD%91%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>对等网络节点组网器。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.remoting.p2p.Networker]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol networker="xxx" /&gt;
&lt;dubbo:provider networker="xxx" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置networker属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.remoting.p2p.support.MulticastNetworker
com.alibaba.dubbo.remoting.p2p.support.FileNetworker]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxNetworker.java (实现Networker接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.remoting.p2p.Networker (纯文本文件,内容为:xxx=com.xxx.XxxNetworker)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxNetworker.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.remoting.p2p.Networker;
public class XxxNetworker implements Networker {
public Group lookup(URL url) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.remoting.p2p.Networker</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxNetworker]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-Telnet%E5%91%BD%E4%BB%A4%E6%89%A9%E5%B1%95"></a>Telnet命令扩展</h3>
<p>(<a href="TelnetHandler+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/TelnetHandler+SPI-zh" title="TelnetHandler SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-Telnet%E5%91%BD%E4%BB%A4%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>所有服务器均支持telnet访问,用于人工干预。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.remoting.telnet.TelnetHandler]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol telnet="xxx,yyy" /&gt;
&lt;dubbo:provider telnet="xxx,yyy" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置telnet属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.remoting.telnet.support.ClearTelnetHandler
com.alibaba.dubbo.remoting.telnet.support.ExitTelnetHandler
com.alibaba.dubbo.remoting.telnet.support.HelpTelnetHandler
com.alibaba.dubbo.remoting.telnet.support.StatusTelnetHandler
com.alibaba.dubbo.rpc.dubbo.telnet.ListTelnetHandler
com.alibaba.dubbo.rpc.dubbo.telnet.ChangeTelnetHandler
com.alibaba.dubbo.rpc.dubbo.telnet.CurrentTelnetHandler
com.alibaba.dubbo.rpc.dubbo.telnet.InvokeTelnetHandler
com.alibaba.dubbo.rpc.dubbo.telnet.TraceTelnetHandler
com.alibaba.dubbo.rpc.dubbo.telnet.CountTelnetHandler
com.alibaba.dubbo.rpc.dubbo.telnet.PortTelnetHandler]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxTelnetHandler.java (实现TelnetHandler接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.remoting.telnet.TelnetHandler (纯文本文件,内容为:xxx=com.xxx.XxxTelnetHandler)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxTelnetHandler.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.remoting.telnet.TelnetHandler;
@Help(parameter="...", summary="...", detail="...")
public class XxxTelnetHandler implements TelnetHandler {
public String telnet(Channel channel, String message) throws RemotingException {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.remoting.telnet.TelnetHandler</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxTelnetHandler]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>用法</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[telnet 127.0.0.1 20880
dubbo&gt; xxx args]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E7%8A%B6%E6%80%81%E6%A3%80%E6%9F%A5%E6%89%A9%E5%B1%95"></a>状态检查扩展</h3>
<p>(<a href="StatusChecker+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/StatusChecker+SPI-zh" title="StatusChecker SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E7%8A%B6%E6%80%81%E6%A3%80%E6%9F%A5%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>检查服务依赖各种资源的状态,此状态检查可同时用于telnet的status命令和hosting的status页面。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.status.StatusChecker]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol status="xxx,yyy" /&gt;
&lt;dubbo:provider status="xxx,yyy" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置status属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.status.support.MemoryStatusChecker
com.alibaba.dubbo.common.status.support.LoadStatusChecker
com.alibaba.dubbo.rpc.dubbo.status.ServerStatusChecker
com.alibaba.dubbo.rpc.dubbo.status.ThreadPoolStatusChecker
com.alibaba.dubbo.registry.directory.RegistryStatusChecker
com.alibaba.dubbo.rpc.config.spring.status.SpringStatusChecker
com.alibaba.dubbo.rpc.config.spring.status.DataSourceStatusChecker]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxStatusChecker.java (实现StatusChecker接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.common.status.StatusChecker (纯文本文件,内容为:xxx=com.xxx.XxxStatusChecker)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxStatusChecker.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.common.status.StatusChecker;
public class XxxStatusChecker implements StatusChecker {
public Status check() {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.common.status.StatusChecker</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxStatusChecker]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E5%AE%B9%E5%99%A8%E6%89%A9%E5%B1%95"></a>容器扩展</h3>
<p>(<a href="Container+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Container+SPI-zh" title="Container SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E5%AE%B9%E5%99%A8%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>服务容器扩展,用于自定义加载内容。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.container.Container]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[java com.alibaba.dubbo.container.Main spring jetty log4j]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.container.spring.SpringContainer
com.alibaba.dubbo.container.spring.JettyContainer
com.alibaba.dubbo.container.spring.Log4jContainer]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxContainer.java (实现Container接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.container.Container (纯文本文件,内容为:xxx=com.xxx.XxxContainer)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxContainer.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
com.alibaba.dubbo.container.Container;
public class XxxContainer implements Container {
public Status start() {
// ...
}
public Status stop() {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.container.Container</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxContainer]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E9%A1%B5%E9%9D%A2%E6%89%A9%E5%B1%95"></a>页面扩展</h3>
<p>(<a href="PageHandler+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/PageHandler+SPI-zh" title="PageHandler SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E9%A1%B5%E9%9D%A2%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>对等网络节点组网器。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.container.page.PageHandler]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol page="xxx,yyy" /&gt;
&lt;dubbo:provider page="xxx,yyy" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:protocol&gt;没有配置page属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.container.page.pages.HomePageHandler
com.alibaba.dubbo.container.page.pages.StatusPageHandler
com.alibaba.dubbo.container.page.pages.LogPageHandler
com.alibaba.dubbo.container.page.pages.SystemPageHandler]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxPageHandler.java (实现PageHandler接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.container.page.PageHandler (纯文本文件,内容为:xxx=com.xxx.XxxPageHandler)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxPageHandler.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.container.page.PageHandler;
public class XxxPageHandler implements PageHandler {
public Group lookup(URL url) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.container.page.PageHandler</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxPageHandler]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E7%BC%93%E5%AD%98%E6%89%A9%E5%B1%95"></a>缓存扩展</h3>
<p>(<a href="CacheFactory+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/CacheFactory+SPI-zh" title="CacheFactory SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E7%BC%93%E5%AD%98%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>用请求参数作为key,缓存返回结果。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.cache.CacheFactory]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service cache="lru" /&gt;
&lt;dubbo:service&gt;&lt;dubbo:method cache="lru" /&gt;&lt;/dubbo:service&gt; &lt;!-- 方法级缓存 --&gt;
&lt;dubbo:provider cache="xxx,yyy" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:service&gt;没有配置cache属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.cache.support.lru.LruCacheFactory
com.alibaba.dubbo.cache.support.threadlocal.ThreadLocalCacheFactory
com.alibaba.dubbo.cache.support.jcache.JCacheFactory]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxCacheFactory.java (实现StatusChecker接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.cache.CacheFactory (纯文本文件,内容为:xxx=com.xxx.XxxCacheFactory)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxCacheFactory.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.cache.CacheFactory;
public class XxxCacheFactory implements CacheFactory {
public Cache getCache(URL url, String name) {
return new XxxCache(url, name);
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxCacheFactory.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.cache.Cache;
public class XxxCache implements Cache {
public Cache(URL url, String name) {
// ...
}
public void put(Object key, Object value) {
// ...
}
public Object get(Object key) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.cache.CacheFactory</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxCacheFactory]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E9%AA%8C%E8%AF%81%E6%89%A9%E5%B1%95"></a>验证扩展</h3>
<p>(<a href="Validation+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Validation+SPI-zh" title="Validation SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E9%AA%8C%E8%AF%81%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>参数验证扩展点。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.validation.Validation]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service validation="xxx,yyy" /&gt;
&lt;dubbo:provider validation="xxx,yyy" /&gt; &lt;!-- 缺省值设置,当&lt;dubbo:service&gt;没有配置validation属性时,使用此配置 --&gt;]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.validation.support.jvalidation.JValidation]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxValidation.java (实现Validation接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.validation.Validation (纯文本文件,内容为:xxx=com.xxx.XxxValidation)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxValidation.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.validation.Validation;
public class XxxValidation implements Validation {
public Object getValidator(URL url) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxValidator.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.validation.Validator;
public class XxxValidator implements Validator {
public XxxValidator(URL url) {
// ...
}
public void validate(Invocation invocation) throws Exception {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.validation.Validation</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxValidation]]></script>
</div></div>
<h3><a name="DeveloperGuide-zh-%E6%97%A5%E5%BF%97%E9%80%82%E9%85%8D%E6%89%A9%E5%B1%95"></a>日志适配扩展</h3>
<p>(<a href="LoggerAdapter+SPI-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/LoggerAdapter+SPI-zh" title="LoggerAdapter SPI-zh">+</a>) (<a href="#DeveloperGuide-zh-%E6%97%A5%E5%BF%97%E9%80%82%E9%85%8D%E6%89%A9%E5%B1%95">#</a>)</p>
<h4><a name="DeveloperGuide-zh-%281%29%E6%89%A9%E5%B1%95%E8%AF%B4%E6%98%8E%EF%BC%9A"></a>(1) 扩展说明:</h4>
<p>日志输出适配扩展点。</p>
<h4><a name="DeveloperGuide-zh-%282%29%E6%89%A9%E5%B1%95%E6%8E%A5%E5%8F%A3%EF%BC%9A"></a>(2) 扩展接口:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.dubbo.common.logger.LoggerAdapter]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%283%29%E6%89%A9%E5%B1%95%E9%85%8D%E7%BD%AE%EF%BC%9A"></a>(3) 扩展配置:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:application logger="xxx" /&gt;]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[-Ddubbo:application.logger=xxx]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%284%29%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95%EF%BC%9A"></a>(4) 已知扩展:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[slf4j=com.alibaba.dubbo.common.logger.slf4j.Slf4jLoggerAdapter
jcl=com.alibaba.dubbo.common.logger.jcl.JclLoggerAdapter
log4j=com.alibaba.dubbo.common.logger.log4j.Log4jLoggerAdapter
jdk=com.alibaba.dubbo.common.logger.jdk.JdkLoggerAdapter]]></script>
</div></div>
<h4><a name="DeveloperGuide-zh-%285%29%E6%89%A9%E5%B1%95%E7%A4%BA%E4%BE%8B%EF%BC%9A"></a>(5) 扩展示例:</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Maven项目结构</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[src
|-main
|-java
|-com
|-xxx
|-XxxLoggerAdapter.java (实现LoggerAdapter接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.common.logger.LoggerAdapter (纯文本文件,内容为:xxx=com.xxx.XxxLoggerAdapter)]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxLoggerAdapter.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.common.logger.LoggerAdapter;
public class XxxLoggerAdapter implements LoggerAdapter {
public Logger getLogger(URL url) {
// ...
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>XxxLogger.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
import com.alibaba.dubbo.common.logger.Logger;
public class XxxLogger implements Logger {
public XxxLogger(URL url) {
// ...
}
public void info(String msg) {
// ...
}
// ...
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>META-INF/dubbo/com.alibaba.dubbo.common.logger.LoggerAdapter</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxx=com.xxx.XxxLoggerAdapter]]></script>
</div></div>
<h2><a name="DeveloperGuide-zh-%E6%8A%80%E6%9C%AF%E5%85%BC%E5%AE%B9%E6%80%A7%E6%B5%8B%E8%AF%95"></a>技术兼容性测试</h2>
<p>(<a href="Technology+Compatibility+Kit-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Technology+Compatibility+Kit-zh" title="Technology Compatibility Kit-zh">+</a>) (<a href="#DeveloperGuide-zh-%E6%8A%80%E6%9C%AF%E5%85%BC%E5%AE%B9%E6%80%A7%E6%B5%8B%E8%AF%95">#</a>)</p>
<p>TCK定义:<a href="javascript:if(confirm(%27http://en.wikipedia.org/wiki/Technology_Compatibility_Kit \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://en.wikipedia.org/wiki/Technology_Compatibility_Kit%27" tppabs="http://en.wikipedia.org/wiki/Technology_Compatibility_Kit" class="external-link" rel="nofollow">http://en.wikipedia.org/wiki/Technology_Compatibility_Kit</a></p>
<p>Dubbo的协议,通讯,序列化,注册中心,负载均策等扩展点,都有多种可选策略,以应对不同应用场景,而我们的测试用例很分散,当用户自己需要加一种新的实现时,总是不确定能否满足扩展点的完整契约。</p>
<p>所以,我们需要对核心扩展点写TCK (Technology Compatibility Kit),用户增加一种扩展实现,只需通过TCK,即可确保与框架的其它部分兼容运行,可以有效提高整体健状性,也方便第三方扩展者接入,加速开源社区的成熟。</p>
<p>开源社区的行知同学已着手研究这一块,他的初步想法是借鉴JBoss的CDI-TCK,做一个Dubbo的TCK基础框架,在此之上实现Dubbo的扩展点TCK用例。</p>
<p>参见:<br/>
<a href="javascript:if(confirm(%27http://docs.jboss.org/cdi/tck/reference/1.0.1-Final/html/introduction.html \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://docs.jboss.org/cdi/tck/reference/1.0.1-Final/html/introduction.html%27" tppabs="http://docs.jboss.org/cdi/tck/reference/1.0.1-Final/html/introduction.html" class="external-link" rel="nofollow">http://docs.jboss.org/cdi/tck/reference/1.0.1-Final/html/introduction.html</a></p>
<p>如果大家有兴趣,也可以一起研究,和行知一块讨论。</p>
<h3><a name="DeveloperGuide-zh-ProtocolTCK"></a>Protocol TCK</h3>
<p>(<a href="Protocol+TCK.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Protocol+TCK" title="Protocol TCK">+</a>) (<a href="#DeveloperGuide-zh-ProtocolTCK">#</a>)</p>
<h3><a name="DeveloperGuide-zh-RegistryTCK"></a>Registry TCK</h3>
<p>(<a href="Registry+TCK.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Registry+TCK" title="Registry TCK">+</a>) (<a href="#DeveloperGuide-zh-RegistryTCK">#</a>)</p>
<h2><a name="DeveloperGuide-zh-%E5%85%AC%E5%85%B1%E5%A5%91%E7%BA%A6"></a>公共契约</h2>
<p>(<a href="Common+Contract-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Common+Contract-zh" title="Common Contract-zh">+</a>) (<a href="#DeveloperGuide-zh-%E5%85%AC%E5%85%B1%E5%A5%91%E7%BA%A6">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>这里记录的是Dubbo公共契约,希望所有扩展点遵守。</td></tr></table></div>
<h3><a name="DeveloperGuide-zh-URL"></a>URL</h3>
<ul>
<li>所有扩展点参数都包含URL参数,URL作为上下文信息贯穿整个扩展点设计体系。</li>
<li>URL采用标准格式:protocol://username:password@host:port/path?key=value&amp;key=value</li>
</ul>
<h3><a name="DeveloperGuide-zh-%E6%97%A5%E5%BF%97"></a>日志</h3>
<ul>
<li>如果不可恢复或需要报警,打印ERROR日志。</li>
<li>如果可恢复异常,或瞬时的状态不一致,打印WARN日志。</li>
<li>正常运行时的中间状态提示,打印INFO日志。</li>
</ul>
<h2><a name="DeveloperGuide-zh-%E5%9D%8F%E5%91%B3%E9%81%93"></a>坏味道</h2>
<p>(<a href="Bad+Smell-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Bad+Smell-zh" title="Bad Smell-zh">+</a>) (<a href="#DeveloperGuide-zh-%E5%9D%8F%E5%91%B3%E9%81%93">&#35;</a>)</p>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>这里记录的是Dubbo设计或实现不优雅的地方。</td></tr></table></div>
<h3><a name="DeveloperGuide-zh-URL%E8%BD%AC%E6%8D%A2"></a>URL转换</h3>
<h4><a name="DeveloperGuide-zh-1.%E7%82%B9%E5%AF%B9%E7%82%B9%E6%9A%B4%E9%9C%B2%E5%92%8C%E5%BC%95%E7%94%A8%E6%9C%8D%E5%8A%A1"></a>1. 点对点暴露和引用服务</h4>
<p>1.1. 直接暴露服务:<br/>
EXPORT(dubbo://provider-address/com.xxx.XxxService?version=1.0.0")</p>
<p>1.2. 点对点直连服务:<br/>
REFER(dubbo://provider-address/com.xxx.XxxService?version=1.0.0)</p>
<h4><a name="DeveloperGuide-zh-2.%E9%80%9A%E8%BF%87%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1"></a>2. 通过注册中心暴露服务</h4>
<p>2.1. 向注册中心暴露服务:<br/>
EXPORT(registry://registry-address/com.alibaba.dubbo.registry.RegistrySerevice?registry=dubbo&amp;export=ENCODE(dubbo://provider-address/com.xxx.XxxService?version=1.0.0))</p>
<p>2.2. 获取注册中心:url.setProtocol(url.getParameter("registry", "dubbo"))<br/>
GETREGISTRY(dubbo://registry-address/com.alibaba.dubbo.registry.RegistrySerevice)</p>
<p>2.3. 注册服务地址:url.getParameterAndDecoded("export"))<br/>
REGISTER(dubbo://provider-address/com.xxx.XxxService?version=1.0.0)</p>
<h4><a name="DeveloperGuide-zh-3.%E9%80%9A%E8%BF%87%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%BC%95%E7%94%A8%E6%9C%8D%E5%8A%A1"></a>3. 通过注册中心引用服务</h4>
<p>3.1. 从注册中心订阅服务:<br/>
REFER(registry://registry-address/com.alibaba.dubbo.registry.RegistrySerevice?registry=dubbo&amp;refer=ENCODE(version=1.0.0))</p>
<p>3.2. 获取注册中心:url.setProtocol(url.getParameter("registry", "dubbo"))<br/>
GETREGISTRY(dubbo://registry-address/com.alibaba.dubbo.registry.RegistrySerevice)</p>
<p>3.3. 订阅服务地址:url.addParameters(url.getParameterAndDecoded("refer"))<br/>
SUBSCRIBE(dubbo://registry-address/com.xxx.XxxService?version=1.0.0)</p>
<p>3.4. 通知服务地址:url.addParameters(url.getParameterAndDecoded("refer"))<br/>
NOTIFY(dubbo://provider-address/com.xxx.XxxService?version=1.0.0)</p>
<h4><a name="DeveloperGuide-zh-4.%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%8E%A8%E9%80%81%E8%B7%AF%E7%94%B1%E8%A7%84%E5%88%99"></a>4. 注册中心推送路由规则</h4>
<p>4.1. 注册中心路由规则推送:<br/>
NOTIFY(route://registry-address/com.xxx.XxxService?router=script&amp;type=js&amp;rule=ENCODE(function{...}))</p>
<p>4.2. 获取路由器:url.setProtocol(url.getParameter("router", "script"))<br/>
GETROUTE(script://registry-address/com.xxx.XxxService?type=js&amp;rule=ENCODE(function{...}))</p>
<h4><a name="DeveloperGuide-zh-5.%E4%BB%8E%E6%96%87%E4%BB%B6%E5%8A%A0%E8%BD%BD%E8%B7%AF%E7%94%B1%E8%A7%84%E5%88%99"></a>5. 从文件加载路由规则</h4>
<p>5.1. 从文件加载路由规则:<br/>
GETROUTE(<a href="file://path/file.js?router=script" class="external-link" rel="nofollow">file://path/file.js?router=script</a>)</p>
<p>5.2. 获取路由器:url.setProtocol(url.getParameter("router", "script")).addParameter("type", SUFFIX(file)).addParameter("rule", READ(file))<br/>
GETROUTE(script://path/file.js?type=js&amp;rule=ENCODE(function{...}))</p>
<h3><a name="DeveloperGuide-zh-%E8%B0%83%E7%94%A8%E5%8F%82%E6%95%B0"></a>调用参数</h3>
<ul>
<li>path 服务路径</li>
<li>group 服务分组</li>
<li>version 服务版本</li>
<li>dubbo 使用的dubbo版本</li>
<li>token 验证令牌</li>
<li>timeout 调用超时</li>
</ul>
<h3><a name="DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E7%9A%84%E5%8A%A0%E8%BD%BD"></a>扩展点的加载</h3>
<h4><a name="DeveloperGuide-zh-1.%E8%87%AA%E9%80%82%E5%BA%94%E6%89%A9%E5%B1%95%E7%82%B9"></a>1. 自适应扩展点</h4>
<p>ExtensionLoader加载扩展点时,会检查扩展点的属性(通过set方法判断),如该属性是扩展点类型,则会注入扩展点对象。因为注入时不能确定使用哪个扩展点(在使用时确定),所以注入的是一个自适应扩展(一个代理)。自适应扩展点调用时,选取一个真正的扩展点,并代理到其上完成调用。Dubbo是根据调用方法参数(上面有调用哪个扩展点的信息)来选取一个真正的扩展点。</p>
<p>在Dubbo给定所有的扩展点上调用都有URL参数(整个扩展点网的上下文信息)。自适应扩展即是从URL确定要调用哪个扩展点实现。URL哪个Key的Value用来确定使用哪个扩展点,这个信息通过的@Adaptive注解在方法上说明。</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[@Extension
public interface Car {
@Adaptive({"http://10.20.160.198/wiki/display/dubbo/car.type", "http://10.20.160.198/wiki/display/dubbo/transport.type"})
public run(URL url, Type1 arg1, Type2 arg2);
}]]></script>
</div></div>
<p>由于自适应扩展点的上面的约定,ExtensionLoader会为扩展点自动生成自适应扩展点类(通过字节码),并将其实例注入。</p>
<p>ExtensionLoader生成的自适应扩展点类如下:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package &lt;扩展点接口所在包&gt;;
public class &lt;扩展点接口名&gt;$Adpative implements &lt;扩展点接口&gt; {
public &lt;有@Adaptive注解的接口方法&gt;(&lt;方法参数&gt;) {
if(是否有URL类型方法参数?) 使用该URL参数
else if(是否有方法类型上有URL属性) 使用该URL属性
# &lt;else 在加载扩展点生成自适应扩展点类时抛异常,即加载扩展点失败!&gt;
if(获取的URL == null) {
throw new IllegalArgumentException("url == null");
}
根据@Adaptive注解上声明的Key的顺序,从URL获致Value,作为实际扩展点名。
URL没有Value,则使用缺省扩展点实现。如没有扩展点, throw new IllegalStateException("Fail to get extension");
在扩展点实现调用该方法,并返回结果。
}
public &lt;有@Adaptive注解的接口方法&gt;(&lt;方法参数&gt;) {
throw new UnsupportedOperationException("is not adaptive method!");
}
}]]></script>
</div></div>
<p>@Adaptive注解使用如下:</p>
<p>如果URL这些Key都没有Value,使用 用 缺省的扩展(在接口的Default中设定的值)。<br/>
比如,String[] {"key1", "key2"},表示 </p>
<p>先在URL上找key1的Value作为要Adapt成的Extension名; <br/>
key1没有Value,则使用key2的Value作为要Adapt成的Extension名。 <br/>
key2没有Value,使用缺省的扩展。 <br/>
如果没有设定缺省扩展,则方法调用会抛出IllegalStateException。 <br/>
如果不设置则缺省使用Extension接口类名的点分隔小写字串。<br/>
即对于Extension接口com.alibaba.dubbo.xxx.YyyInvokerWrapper的缺省值为String[] {"yyy.invoker.wrapper"}</p>
<h3><a name="DeveloperGuide-zh-Callback%E5%8A%9F%E8%83%BD"></a>Callback功能</h3>
<h4><a name="DeveloperGuide-zh-1.%E5%8F%82%E6%95%B0%E5%9B%9E%E8%B0%83"></a>1. 参数回调</h4>
<p>1.1主要原理:在一个Consumer-&gt;provider的长连接上,自动在Consumer端暴露一个服务(实现方法参数上声明的接口A),provider端便可反向调用到consumer端的接口实例.<br/>
1.2实现细节:</p>
<ul>
<li>为了在传输时能够对回调接口实例进行转换,自动暴露与自动引用目前在DubboCodec中实现.此处需要考虑将此逻辑与codec逻辑分离.</li>
<li>在根据invocation信息获取exporter时,需要判断是否是回调,如果是回调,会从attachments中取得回调服务实例的id,在获取exporter,此处用于consumer端可以对同一个callback接口做不同的实现。</li>
</ul>
<h4><a name="DeveloperGuide-zh-2.%E4%BA%8B%E4%BB%B6%E9%80%9A%E7%9F%A5"></a>2. 事件通知</h4>
<p>2.1主要原理:Consumer在invoke方法时,判断如果有配置onreturn/onerror...则将onreturn对应的参数值(实例方法)加入到异步调用的回调列表中.<br/>
2.2实现细节:参数的传递采用URL,但URL中没有支持string-object,所以将实例方法存储在staticMap中,此处实现需要进行改造,<a href="javascript:if(confirm(%27http://code.alibabatech.com/jira/browse/DUBBO-168 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://code.alibabatech.com/jira/browse/DUBBO-168%27" tppabs="http://code.alibabatech.com/jira/browse/DUBBO-168" class="external-link" rel="nofollow">http://code.alibabatech.com/jira/browse/DUBBO-168</a></p>
<h3><a name="DeveloperGuide-zh-Lazy%E8%BF%9E%E6%8E%A5"></a>Lazy连接</h3>
<p>DubboProtocol特有功能,默认关闭<br/>
当客户端与服务端创建代理时,暂不建立tcp长连接,当有数据请求时在做连接初始化<br/>
此项功能自动关闭连接重试功能,开启发送重试功能(即发送数据时如果连接已断开,尝试重新建立连接).</p>
<h3><a name="DeveloperGuide-zh-%E5%85%B1%E4%BA%AB%E8%BF%9E%E6%8E%A5"></a>共享连接</h3>
<p>DubboProtocol特有功能,默认开启<br/>
JVM A暴露了多个服务,JVM B引用了A中的多个服务,共享连接是说A与B多个服务调用是通过同一个TCP长连接进行数据传输,已达到减少服务端连接数的目的.<br/>
实现细节:对于同一个地址由于使用了共享连接,那invoker的destroy就需要特别注意,一方面要满足对同一个地址refer的invoker全部destroy后,连接需要关闭,另一方面还需要注意如何避免部分invoker destroy时不能关闭连接。在实现中采用了引用计数的方案,但为了防范,在连接关闭时,重新建立了一个Lazy connection(称为幽灵连接),用于当出现异常场景时,避免影响业务逻辑的正常调用.</p>
<h3><a name="DeveloperGuide-zh-sticky%E7%AD%96%E7%95%A5"></a>sticky 策略</h3>
<p>有多个服务提供者的情况下,配置了sticky后,在提供者可用的情况下,调用会继续发送到上一次的服务提供者. sticky策略默认开启了连接的lazy选项,用于避免开启无用的连接.</p>
<h3><a name="DeveloperGuide-zh-%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E9%80%89%E6%8B%A9%E9%80%BB%E8%BE%91"></a>服务提供者选择逻辑</h3>
<p>1.存在多个服务提供者的情况下,首先根据Loadbalance进行选择,如果选择的provider处于可用状态,则进行后续调用<br/>
2.如果第一步选择的服务提供者不可用,则从剩余服务提供者列表中继续选择,如果可用,进行后续调用<br/>
3.如果所有的服务提供者都不可用,重新遍历整个列表(优先从没有选过的列表中选择),判断是否有可用的服务提供者(选择过程中,不可用的服务提供者可能会恢复到可用状态),如果有,则进行后续调用<br/>
4.如果第三步没有选择出可用的服务提供者,会选第一步选出的invoker中的下一个(如果不是最后一个),避免碰撞.</p>
<h2><a name="DeveloperGuide-zh-%E7%BC%96%E7%A0%81%E7%BA%A6%E5%AE%9A"></a>编码约定</h2>
<p>(<a href="Code+Conventions-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Code+Conventions-zh" title="Code Conventions-zh">+</a>) (<a href="#DeveloperGuide-zh-%E7%BC%96%E7%A0%81%E7%BA%A6%E5%AE%9A">#</a>)</p>
<p>Source code and documentation contributed to the Dubbo repositories should observe the:</p>
<ul>
<li><a href="javascript:if(confirm(%27http://www.oracle.com/technetwork/java/codeconvtoc-136057.html \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.oracle.com/technetwork/java/codeconvtoc-136057.html%27" tppabs="http://www.oracle.com/technetwork/java/codeconvtoc-136057.html" class="external-link" rel="nofollow">Code Conventions for the Java Programming Language</a></li>
<li><a href="javascript:if(confirm(%27http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html%27" tppabs="http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html" class="external-link" rel="nofollow">How to Write Doc Comments for the Javadoc Tool</a></li>
</ul>
<p>as core references regarding the formatting of code and documentation.</p>
<ul>
<li>异常和日志:
<ul>
<li>尽可能携带完整的上下文信息,比如出错原因,出错的机器地址,调用对方的地址,连的注册中心地址,使用Dubbo的版本等。</li>
<li>尽量将直接原因写在最前面,所有上下文信息,在原因后用键值对显示。</li>
<li>抛出异常的地方不用打印日志,由最终处理异常者决定打印日志的级别,吃掉异常必需打印日志。</li>
<li>打印ERROR日志表示需要报警,打印WARN日志表示可以自动恢复,打印INFO表示正常信息或完全不影响运行。</li>
<li>建议应用方在监控中心配置ERROR日志实时报警,WARN日志每周汇总发送通知。</li>
<li>RpcException是Dubbo对外的唯一异常类型,所有内部异常,如果要抛出给用户,必须转为RpcException。</li>
<li>RpcException不能有子类型,所有类型信息用ErrorCode标识,以便保持兼容。</li>
</ul>
</li>
<li>配置和URL:
<ul>
<li>配置对象属性首字母小写,多个单词用驼峰命名(Java约定)。</li>
<li>配置属性全部用小写,多个单词用"-"号分隔(Spring约定)。</li>
<li>URL参数全部用小写,多个单词用"."号分隔(Dubbo约定)。</li>
<li>尽可能用URL传参,不要自定义Map或其它上下文格式,配置信息也转成URL格式使用。</li>
<li>尽量减少URL嵌套,保持URL的简洁性。</li>
</ul>
</li>
<li>单元和集成测试:
<ul>
<li>单元测试统一用JUnit和EasyMock,集成测试用TestNG,数据库测试用DBUnit。</li>
<li>保持单元测试用例的运行速度,不要将性能和大的集成用例放在单元测试中。</li>
<li>保持单元测试的每个用例都用try...finally或tearDown释放资源。</li>
<li>减少while循环等待结果的测试用例,对定时器和网络的测试,用以将定时器中的逻辑抽为方法测试。</li>
<li>对于容错行为的测试,比如failsafe的测试,统一用LogUtil断言日志输出。</li>
</ul>
</li>
<li>扩展点基类与AOP:
<ul>
<li>AOP类都命名为XxxWrapper,基类都命名为AbstractXxx。</li>
<li>扩展点之间的组合将关系由AOP完成,ExtensionLoader只负载加载扩展点,包括AOP扩展。</li>
<li>尽量采用IoC注入扩展点之间的依赖,不要直接依赖ExtensionLoader的工厂方法。</li>
<li>尽量采用AOP实现扩展点的通用行为,而不要用基类,比如负载均衡之前的isAvailable检查,它是独立于负载均衡之外的,不需要检查的是URL参数关闭。</li>
<li>对多种相似类型的抽象,用基类实现,比如RMI,Hessian等第三方协议都已生成了接口代理,只需将将接口代理转成Invoker即可完成桥接,它们可以用公共基类实现此逻辑。</li>
<li>基类也是SPI的一部分,每个扩展点都应该有方便使用的基类支持。</li>
</ul>
</li>
<li>模块与分包:
<ul>
<li>基于复用度分包,总是一起使用的放在同一包下,将接口和基类分成独立模块,大的实现也使用独立模块。</li>
<li>所有接口都放在模块的根包下,基类放在support子包下,不同实现用放在以扩展点名字命名的子包下。</li>
<li>尽量保持子包依赖父包,而不要反向。</li>
</ul>
</li>
</ul>
<h2><a name="DeveloperGuide-zh-%E6%A3%80%E6%9F%A5%E5%88%97%E8%A1%A8"></a>检查列表</h2>
<p>(<a href="Check+List-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Check+List-zh" title="Check List-zh">+</a>) (<a href="#DeveloperGuide-zh-%E6%A3%80%E6%9F%A5%E5%88%97%E8%A1%A8">#</a>)</p>
<p>1. 发布前checklist:<br/>
1.1 jira ticket 过一遍<br/>
1.2 svn change list<br/>
1.3 ticket关联code<br/>
1.4 test code<br/>
1.5 find bugs </p>
<p>2. 修复时checklist:<br/>
2.1 修复代码前先建ticket <br/>
2.2 修复代码前先写测试用例<br/>
2.3 需要伙伴检查<br/>
2.4 test code(正常流程/异常流程)<br/>
2.5 讲一遍逻辑<br/>
2.6 契约文档化<br/>
2.7 以上内容都写到ticket的评论上<br/>
2.8 代码注释写清楚,用中文无妨<br/>
2.9 每个版本要有owner,确保scope和check</p>
<p>3. Partner Check<br/>
3.1 Partner以用户的方式运行一下功能<br/>
3.2 Partner发现问题、添加测试(集成测试)复现总是;Owner完成实现。(保证两方的时间投入PatternerCheck 的给予时间保证)<br/>
3.3 Owner向Partner讲述一遍实现。</p>
<h2><a name="DeveloperGuide-zh-%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99"></a>设计原则</h2>
<p>(<a href="Design+Principles-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Design+Principles-zh" title="Design Principles-zh">+</a>) (<a href="#DeveloperGuide-zh-%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99">#</a>)</p>
<ul>
<li><a href="javascript:if(confirm(%27http://javatar.iteye.com/blog/1056664 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://javatar.iteye.com/blog/1056664%27" tppabs="http://javatar.iteye.com/blog/1056664" class="external-link" rel="nofollow">魔鬼在细节中</a></li>
<li><a href="javascript:if(confirm(%27http://javatar.iteye.com/blog/706098 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://javatar.iteye.com/blog/706098%27" tppabs="http://javatar.iteye.com/blog/706098" class="external-link" rel="nofollow">一些设计上的基本常识</a></li>
<li><a href="javascript:if(confirm(%27http://javatar.iteye.com/blog/690845 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://javatar.iteye.com/blog/690845%27" tppabs="http://javatar.iteye.com/blog/690845" class="external-link" rel="nofollow">谈谈扩充式扩展与增量式扩展</a></li>
<li><a href="javascript:if(confirm(%27http://javatar.iteye.com/blog/949527 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://javatar.iteye.com/blog/949527%27" tppabs="http://javatar.iteye.com/blog/949527" class="external-link" rel="nofollow">配置设计</a></li>
<li><a href="javascript:if(confirm(%27http://oldratlee.com/380/tech/java/robustness-of-implement.html \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://oldratlee.com/380/tech/java/robustness-of-implement.html%27" tppabs="http://oldratlee.com/380/tech/java/robustness-of-implement.html" class="external-link" rel="nofollow">设计实现的健壮性</a></li>
<li><a href="javascript:if(confirm(%27http://javatar.iteye.com/blog/804187 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://javatar.iteye.com/blog/804187%27" tppabs="http://javatar.iteye.com/blog/804187" class="external-link" rel="nofollow">防痴呆设计</a></li>
<li><a href="javascript:if(confirm(%27http://javatar.iteye.com/blog/1041832 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://javatar.iteye.com/blog/1041832%27" tppabs="http://javatar.iteye.com/blog/1041832" class="external-link" rel="nofollow">扩展点重构</a></li>
</ul>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/6948815"/>
</rdf:RDF>
-->
<fieldset class="hidden parameters">
<legend>Labels parameters</legend>
<input type="hidden" id="domainName" value="http://code.alibabatech.com/wiki">
<input type="hidden" id="pageId" value="6948815">
<input type="hidden" id="spaceKey" value="dubbo">
</fieldset>
<div id="labels-section" class="pageSection">
<div class="labels-editor">
<span id="labels-section-title" class="label-title">
<b>Labels:</b>
</span>
<div id="labels-section-content" class="content-column">
<span id="labels-section-title-none" class="label-title none hidden ">
None
</span>
<div id="labelsList" class="label-list">
<div id="label-7307267" class="confluence-label">
<a class="label" rel="nofollow" href="javascript:if(confirm(%27http://10.20.160.198/wiki/label/dubbo/dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/label/dubbo/dubbo%27" tppabs="http://10.20.160.198/wiki/label/dubbo/dubbo">dubbo</a> <span class="remove-label-caption">dubbo</span>
<a class="remove-label" href="#">Delete</a>
</div>
<div id="label-7307271" class="confluence-label">
<a class="label" rel="nofollow" href="javascript:if(confirm(%27http://10.20.160.198/wiki/label/dubbo/developer \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/label/dubbo/developer%27" tppabs="http://10.20.160.198/wiki/label/dubbo/developer">developer</a> <span class="remove-label-caption">developer</span>
<a class="remove-label" href="#">Delete</a>
</div>
<div id="label-7307270" class="confluence-label">
<a class="label" rel="nofollow" href="javascript:if(confirm(%27http://10.20.160.198/wiki/label/dubbo/guide \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/label/dubbo/guide%27" tppabs="http://10.20.160.198/wiki/label/dubbo/guide">guide</a> <span class="remove-label-caption">guide</span>
<a class="remove-label" href="#">Delete</a>
</div>
<div id="label-7307298" class="confluence-label">
<a class="label" rel="nofollow" href="javascript:if(confirm(%27http://10.20.160.198/wiki/label/dubbo/zh \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/label/dubbo/zh%27" tppabs="http://10.20.160.198/wiki/label/dubbo/zh">zh</a> <span class="remove-label-caption">zh</span>
<a class="remove-label" href="#">Delete</a>
</div>
</div>
</div>
<span class="errorMessage error" id="errorSpan"></span>
<form method="GET" action="" id="add-labels-form">
<div id="labelInputSpan" class="labels-input">
<div id="labelOperationErrorContainer" class="hidden">
<span class="error"><span class="errorMessage" id="labelOperationErrorMessage"></span></span>
</div>
<div class="caption">Enter labels to add to this page:</div>
<div id="label-input-fields">
<input autocomplete="off" id="labelsString" name="labelsString" value="" size="40">
<input id="add-labels-editor-button" type="submit" class="add-labels" value="Add">
<input id="close-labels-editor-button" type="submit" class="hide-labels-editor" value="Done">
</div>
<div id="waitImageAndStatus">
<img class="waiting" alt="Please wait" src="wait.gif" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/wait.gif">&nbsp;
<span id="labelOperationStatus" class="smalltext"></span>
</div>
<div id="labelsAutocompleteList" class="aui-dd-parent"></div>
<div class="labels-tip">
<div id="suggestedLabelsSpan"></div>
Looking for a label? Just start typing.
</div>
</div>
</form>
</div>
</div>
<div id="children-section" class="pageSection children-hidden">
<div class="section-header summary">
<h2 id="children-section-title" class="section-title">
<a href="Developer+Guide-zh-showChildren=true.htm#children" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?showChildren=true#children" class="children-show-hide">
13 Child Pages
</a>
</h2>
<a href="Developer+Guide-zh-showChildren=true.htm#children" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?showChildren=true#children" class="children-show-hide icon"></a>
<span class="noprint grey">
<a class="children-subtitle" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/listpages-dirview.action?key=dubbo&openId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/listpages-dirview.action?key=dubbo&openId=6948815#selectedPageInHierarchy%27" tppabs="http://10.20.160.198/wiki/pages/listpages-dirview.action?key=dubbo&openId=6948815#selectedPageInHierarchy">Reorder Pages</a>
</span>
</div>
<div id="page-children" class="pageSectionBody">
</div>
</div>
<fieldset class="parameters hidden">
<input type="hidden" id="deleteCommentConfirmMessage" value="Are you sure you want to remove the comment?">
<input type="hidden" id="collapseTooltip" value="Click to toggle the display of this comment.">
</fieldset>
<fieldset class="hidden parameters i18n">
<input type="hidden" title="i18n.cancel.name" value="Cancel">
</fieldset>
<div id="comments-section" class="pageSection">
<div class="section-header ">
<h2 id="comments-section-title" class="section-title">
<a href="#" class="comments-show-hide comments-showing" name="comments">
11 Comments
</a>
</h2>
<a title="comments.show.hide" href="#"
class="comments-show-hide icon comments-showing icon-section-opened">
comments.show.hide
</a>
</div>
<ol class="comment-threads top-level " id="page-comments">
<li id="comment-thread-7674361" class="comment-thread">
<div class="comment " id="comment-7674361">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="十月 18, 2012 23:48">
十月 18, 2012
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>请问这玩意怎么从0开始起起一个HelloWorld</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=7674361.htm#comment-7674361" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=7674361#comment-7674361"
id="comment-permalink-7674361" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=7674361&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=7674361&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=7674361&pageId=6948815"
id="reply-comment-7674361" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=7674361#comment-7674361"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=7674361#comment-7674361"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/7674361"/>
</rdf:RDF>
-->
<ol class="comment-threads">
<li id="comment-thread-8781850" class="comment-thread">
<div class="comment " id="comment-8781850">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="二月 14, 2013 11:12">
二月 14, 2013
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>Son of a gun, this is so hleupfl!</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=8781850.htm#comment-8781850" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781850#comment-8781850"
id="comment-permalink-8781850" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781850&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781850&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781850&pageId=6948815"
id="reply-comment-8781850" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781850#comment-8781850"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781850#comment-8781850"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/8781850"/>
</rdf:RDF>
-->
</li>
<li id="comment-thread-8781863" class="comment-thread">
<div class="comment " id="comment-8781863">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="二月 16, 2013 20:47">
二月 16, 2013
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>I can already tell that's gonna be super heuplfl.</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=8781863.htm#comment-8781863" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781863#comment-8781863"
id="comment-permalink-8781863" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781863&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781863&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781863&pageId=6948815"
id="reply-comment-8781863" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781863#comment-8781863"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781863#comment-8781863"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/8781863"/>
</rdf:RDF>
-->
</li>
<li id="comment-thread-8781873" class="comment-thread">
<div class="comment focused " id="comment-8781873">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="二月 19, 2013 13:08">
二月 19, 2013
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>g3hS39 &lt;a href="http://zbynxenqweay.com/"&gt;zbynxenqweay&lt;/a&gt;</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=8781873.htm#comment-8781873" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781873#comment-8781873"
id="comment-permalink-8781873" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781873&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781873&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781873&pageId=6948815"
id="reply-comment-8781873" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781873#comment-8781873"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781873#comment-8781873"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/8781873"/>
</rdf:RDF>
-->
</li>
</ol>
</li>
<li id="comment-thread-8356031" class="comment-thread">
<div class="comment " id="comment-8356031">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="一月 22, 2013 22:36">
一月 22, 2013
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>怎么没有注册功能了?</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=8356031.htm#comment-8356031" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8356031#comment-8356031"
id="comment-permalink-8356031" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8356031&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8356031&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=8356031&pageId=6948815"
id="reply-comment-8356031" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8356031#comment-8356031"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8356031#comment-8356031"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/8356031"/>
</rdf:RDF>
-->
</li>
<li id="comment-thread-8781989" class="comment-thread">
<div class="comment " id="comment-8781989">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="四月 22, 2013 16:46">
四月 22, 2013
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>想问下管理平台保存的路由信息保存再哪里?我重启了zookeeper和管理平台后,还是出现,而且无法失效和删除,需要删除<br/>
缓存文件,想问下保存在哪?如何删除,谢谢</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=8781989.htm#comment-8781989" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781989#comment-8781989"
id="comment-permalink-8781989" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781989&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781989&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=8781989&pageId=6948815"
id="reply-comment-8781989" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781989#comment-8781989"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8781989#comment-8781989"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/8781989"/>
</rdf:RDF>
-->
</li>
<li id="comment-thread-8782094" class="comment-thread">
<div class="comment " id="comment-8782094">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="六月 22, 2013 16:27">
六月 22, 2013
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>What the hell is this ? So complicated.</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=8782094.htm#comment-8782094" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782094#comment-8782094"
id="comment-permalink-8782094" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782094&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782094&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782094&pageId=6948815"
id="reply-comment-8782094" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782094#comment-8782094"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782094#comment-8782094"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/8782094"/>
</rdf:RDF>
-->
</li>
<li id="comment-thread-8782183" class="comment-thread">
<div class="comment " id="comment-8782183">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="七月 29, 2013 15:02">
七月 29, 2013
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>大家注意哈,自己下载源代码编译的时候,最好是maven版本是2.x的,我使用maven3.0.3出现:<br/>
Could not find metadata org.apache.maven.plugins/maven-metadata.xml in opensesame.snapshots.plugin (<a href="javascript:if(confirm(%27http://code.alibabatech.com/mvn/snapshots \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://code.alibabatech.com/mvn/snapshots%27" tppabs="http://code.alibabatech.com/mvn/snapshots" class="external-link" rel="nofollow">http://code.alibabatech.com/mvn/snapshots</a>)<br/>
<span class="error">&#91;DEBUG&#93;</span> Could not find metadata org.apache.maven.plugins/maven-metadata.xml in opensesame.releases.plugin (<a href="javascript:if(confirm(%27http://code.alibabatech.com/mvn/releases \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://code.alibabatech.com/mvn/releases%27" tppabs="http://code.alibabatech.com/mvn/releases" class="external-link" rel="nofollow">http://code.alibabatech.com/mvn/releases</a>)<br/>
<span class="error">&#91;DEBUG&#93;</span> Could not find metadata org.codehaus.mojo/maven-metadata.xml in opensesame.snapshots.plugin (<a href="javascript:if(confirm(%27http://code.alibabatech.com/mvn/snapshots \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://code.alibabatech.com/mvn/snapshots%27" tppabs="http://code.alibabatech.com/mvn/snapshots" class="external-link" rel="nofollow">http://code.alibabatech.com/mvn/snapshots</a>)<br/>
异常:<br/>
org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException: No plugin found for prefix 'X' in the current project and in the plugin groups <span class="error">&#91;org.apache.maven.plugins, org.codehaus.mojo&#93;</span> available from the repositories <span class="error">&#91;local (/Users/kyle/.m2/repository), central.repo.plugin (http://repo1.maven.org/maven2), opensesame.snapshots.plugin (http://code.alibabatech.com/mvn/snapshots), opensesame.releases.plugin (http://code.alibabatech.com/mvn/releases), central (http://repo1.maven.org/maven2)&#93;</span></p>
<p>这个问题,换成maven2.2.1编译,就OK了!</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=8782183.htm#comment-8782183" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782183#comment-8782183"
id="comment-permalink-8782183" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782183&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782183&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782183&pageId=6948815"
id="reply-comment-8782183" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782183#comment-8782183"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782183#comment-8782183"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/8782183"/>
</rdf:RDF>
-->
<ol class="comment-threads">
<li id="comment-thread-8782193" class="comment-thread">
<div class="comment " id="comment-8782193">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="八月 01, 2013 11:36">
八月 01, 2013
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>好些jar包找不到啊~比如:hessian-lite 这个貌似是ali内部精简的一个包,在maven仓库找不到</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=8782193.htm#comment-8782193" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782193#comment-8782193"
id="comment-permalink-8782193" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782193&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782193&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782193&pageId=6948815"
id="reply-comment-8782193" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782193#comment-8782193"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782193#comment-8782193"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/8782193"/>
</rdf:RDF>
-->
</li>
</ol>
</li>
<li id="comment-thread-8782213" class="comment-thread">
<div class="comment " id="comment-8782213">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="八月 07, 2013 18:47">
八月 07, 2013
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>弱弱的问一下: ServiceConfig里面的<br/>
private void checkProtocol() {<br/>
if ((protocols == null || protocols.size() == 0)<br/>
&amp;&amp; provider != null) </p>
<div class="error"><span class="error">Unknown macro: {
setProtocols(provider.getProtocols());
}</span> </div>
<p> // 兼容旧版本<br/>
if (protocols == null || protocols.size() == 0) </p>
<div class="error"><span class="error">Unknown macro: {
setProtocol(new ProtocolConfig());
}</span> </div>
<p> for (ProtocolConfig protocolConfig : protocols) {<br/>
if (StringUtils.isEmpty(protocolConfig.getName())) </p>
<div class="error"><span class="error">Unknown macro: {
protocolConfig.setName(&quot;dubbo&quot;);
}</span> </div>
<p> appendProperties(protocolConfig);<br/>
}<br/>
}中的那个"dubbo"会出错吗?这样设置以后好像最后不能使用dubbo.properties里面的全局设置了,是这样的?</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=8782213.htm#comment-8782213" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782213#comment-8782213"
id="comment-permalink-8782213" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782213&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782213&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782213&pageId=6948815"
id="reply-comment-8782213" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782213#comment-8782213"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782213#comment-8782213"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/8782213"/>
</rdf:RDF>
-->
</li>
<li id="comment-thread-8782350" class="comment-thread">
<div class="comment " id="comment-8782350">
<p class="comment-user-logo">
<img class="userLogo logo anonymous" src="anonymous.png" tppabs="http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/profilepics/anonymous.png"
alt="User icon: Anonymous" title="Anonymous"> </p>
<p class="date" title="九月 03, 2013 10:22">
九月 03, 2013
</p>
<div class="comment-header">
<h4 class="author">Anonymous</h4>
</div>
<div class="comment-body">
<div class="comment-content wiki-content">
<p>问下,Dubbo已经不更新了吗,我看到好多任务都没人认领?</p>
</div>
<div class="comment-actions">
<ul id="comment-actions-secondary">
<li class="first comment-permalink">
<a title="Permanent link to this comment" href="Developer+Guide-zh-focusedCommentId=8782350.htm#comment-8782350" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782350#comment-8782350"
id="comment-permalink-8782350" ><span>Permalink</span></a></li>
</ul>
<ul id="comment-actions-primary">
<li class="first action-reply-comment">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782350&pageId=6948815 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782350&pageId=6948815%27" tppabs="http://10.20.160.198/wiki/pages/replycomment.action?commentId=8782350&pageId=6948815"
id="reply-comment-8782350" ><span>Reply</span></a></li>
</ul>
</div>
</div>
</div>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782350#comment-8782350"
dc:identifier="http://code.alibabatech.com/wiki/display/dubbo/Developer+Guide-zh?focusedCommentId=8782350#comment-8782350"
dc:title="Developer Guide-zh"
trackback:ping="http://code.alibabatech.com/wiki/rpc/trackback/8782350"/>
</rdf:RDF>
-->
</li>
</ol>
<a id="add-comment-bottom" href="Developer+Guide-zh-showComments=true&showCommentArea=true.htm#addcomment" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh?showComments=true&showCommentArea=true#addcomment">
Add Comment
</a>
</div>
</div>
<script type="text/x-template" title="manage-watchers-dialog">
<div class="dialog-content">
<div class="column page-watchers">
<h3>Watching this page</h3>
<p class="description">These people are notified when the page is changed. You can add or remove people from this list.</p>
<form action="/wiki/json/addwatch.action" method="POST">
<input type="hidden" name="atl_token" value="c116db80711201b36e2067aa83f3b044c2d5a30e">
<input type="hidden" name="pageId" value="6948815"/>
<input type="hidden" id="add-watcher-username" name="username" value=""/>
<label for="add-watcher-user">User</label>
<input id="add-watcher-user" name="userFullName" type="search" class="autocomplete-user"
value="" placeholder="Full name or username" autocomplete="off"
data-max="10" data-target="#add-watcher-username" data-dropdown-target="#add-watcher-dropdown"
data-template="{title}" data-none-message="No matching users found.">
<input id="add-watcher-submit" type="submit" name="add" value="Add">
<div id="add-watcher-dropdown" class="aui-dd-parent autocomplete"></div>
<div class="status hidden"></div>
</form>
<ul class="user-list">
<li class="loading">Loading&hellip;</li>
<li class="no-users hidden">No page watchers</li>
</ul>
</div>
<div class="column space-watchers">
<h3>Watching this space</h3>
<p class="description">These people are notified when any content in the space is changed. You cannot modify this list.</p>
<ul class="user-list">
<li class="loading">Loading&hellip;</li>
<li class="no-users hidden">No space watchers</li>
</ul>
</div>
</div>
</script>
<script type="text/x-template" title="manage-watchers-user">
<li class="watch-user">
<img class="profile-picture confluence-userlink" src="{iconUrl}" data-username="{username}">
<a class="confluence-userlink" href="{url}" data-username="{username}">{fullName} <span class="username">({username})</span></a>
<span class="remove-watch" title="Remove"
data-username="{username}">Remove</span>
</li>
</script>
<script type="text/x-template" title="manage-watchers-help-link">
<div class="dialog-help-link">
<a href="http://docs.atlassian.com/confluence/docs-35/Managing+Watchers" target="_blank">Help</a>
</div>
</script>
<br class="clear">
</div><!-- \#main -->
<div id="footer">
<p class="license license-opensource">
Powered by a free <b>Atlassian Confluence Open Source Project License</b> granted to Alibaba Tech. <a href="javascript:if(confirm(%27http://www.atlassian.com/c/conf/11461 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.atlassian.com/c/conf/11461%27" tppabs="http://www.atlassian.com/c/conf/11461">Evaluate Confluence today</a>.<br>
</p>
<ul id="poweredby">
<li class="noprint">Powered by <a href="javascript:if(confirm(%27http://www.atlassian.com/software/confluence \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.atlassian.com/software/confluence%27" tppabs="http://www.atlassian.com/software/confluence" class="hover-footer-link">Atlassian Confluence</a> 3.5.9, the <a href="javascript:if(confirm(%27http://www.atlassian.com/software/confluence/tour/enterprise-wiki.jsp \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.atlassian.com/software/confluence/tour/enterprise-wiki.jsp%27" tppabs="http://www.atlassian.com/software/confluence/tour/enterprise-wiki.jsp" class="hover-footer-link">Enterprise Wiki</a></li>
<li class="print-only">Printed by Atlassian Confluence 3.5.9, the Enterprise Wiki.</li>
<li class="noprint"> &nbsp; |&nbsp; <a href="javascript:if(confirm(%27http://jira.atlassian.com/secure/BrowseProject.jspa?id=10470 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://jira.atlassian.com/secure/BrowseProject.jspa?id=10470%27" tppabs="http://jira.atlassian.com/secure/BrowseProject.jspa?id=10470" class="hover-footer-link">Report a bug</a></li>
<li class="noprint"> &nbsp;|&nbsp; <a href="javascript:if(confirm(%27http://www.atlassian.com/about/connected.jsp?s_kwcid=Confluence-stayintouch \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://www.atlassian.com/about/connected.jsp?s_kwcid=Confluence-stayintouch%27" tppabs="http://www.atlassian.com/about/connected.jsp?s_kwcid=Confluence-stayintouch" class="hover-footer-link">Atlassian News</a></li>
</ul>
友情链接:<a href="javascript:if(confirm(%27http://code.taobao.org/ \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://code.taobao.org/%27" tppabs="http://code.taobao.org/">Taocode</a>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-31474478-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www/') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</div></div><!-- \#full-height-container -->
</div><!-- \#page -->
</body>
</html>