| |
| <!DOCTYPE HTML> |
| <html lang="" > |
| <head> |
| <meta charset="UTF-8"> |
| <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> |
| <title>5 扩展点加载 · GitBook</title> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge" /> |
| <meta name="description" content=""> |
| <meta name="generator" content="GitBook 3.2.2"> |
| |
| |
| |
| |
| <link rel="stylesheet" href="gitbook/style.css"> |
| |
| |
| |
| |
| <link rel="stylesheet" href="gitbook/gitbook-plugin-highlight/website.css"> |
| |
| |
| |
| <link rel="stylesheet" href="gitbook/gitbook-plugin-search/search.css"> |
| |
| |
| |
| <link rel="stylesheet" href="gitbook/gitbook-plugin-fontsettings/website.css"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <meta name="HandheldFriendly" content="true"/> |
| <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> |
| <meta name="apple-mobile-web-app-capable" content="yes"> |
| <meta name="apple-mobile-web-app-status-bar-style" content="black"> |
| <link rel="apple-touch-icon-precomposed" sizes="152x152" href="gitbook/images/apple-touch-icon-precomposed-152.png"> |
| <link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon"> |
| |
| |
| <link rel="next" href="SPI参考手册/introduction.html" /> |
| |
| |
| <link rel="prev" href="框架设计.html" /> |
| |
| |
| </head> |
| <body> |
| |
| <div class="book"> |
| <div class="book-summary"> |
| |
| |
| <div id="book-search-input" role="search"> |
| <input type="text" placeholder="Type to search" /> |
| </div> |
| |
| |
| <nav role="navigation"> |
| |
| |
| |
| <ul class="summary"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="chapter " data-level="1.1" data-path="./"> |
| |
| <a href="./"> |
| |
| |
| Introduction |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.2" data-path="contribution.html"> |
| |
| <a href="contribution.html"> |
| |
| |
| 1 contribution |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.3" data-path="版本管理.html"> |
| |
| <a href="版本管理.html"> |
| |
| |
| 2 版本管理 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.4" data-path="源码构建.html"> |
| |
| <a href="源码构建.html"> |
| |
| |
| 3 源码构建 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.5" data-path="框架设计.html"> |
| |
| <a href="框架设计.html"> |
| |
| |
| 4 框架设计 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter active" data-level="1.6" data-path="扩展点加载.html"> |
| |
| <a href="扩展点加载.html"> |
| |
| |
| 5 扩展点加载 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7" data-path="SPI参考手册/introduction.html"> |
| |
| <a href="SPI参考手册/introduction.html"> |
| |
| |
| 6 SPI参考手册 |
| |
| </a> |
| |
| |
| |
| <ul class="articles"> |
| |
| |
| <li class="chapter " data-level="1.7.1" data-path="SPI参考手册/协议扩展.html"> |
| |
| <a href="SPI参考手册/协议扩展.html"> |
| |
| |
| 6.1 协议扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.2" data-path="SPI参考手册/调用拦截扩展.html"> |
| |
| <a href="SPI参考手册/调用拦截扩展.html"> |
| |
| |
| 6.2 调用拦截扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.3" data-path="SPI参考手册/引用监听扩展.html"> |
| |
| <a href="SPI参考手册/引用监听扩展.html"> |
| |
| |
| 6.3 引用监听扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.4" data-path="SPI参考手册/暴露监听扩展.html"> |
| |
| <a href="SPI参考手册/暴露监听扩展.html"> |
| |
| |
| 6.4 暴露监听扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.5" data-path="SPI参考手册/集群扩展.html"> |
| |
| <a href="SPI参考手册/集群扩展.html"> |
| |
| |
| 6.5 集群扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.6" data-path="SPI参考手册/路由扩展.html"> |
| |
| <a href="SPI参考手册/路由扩展.html"> |
| |
| |
| 6.6 路由扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.7" data-path="SPI参考手册/负载均衡扩展.html"> |
| |
| <a href="SPI参考手册/负载均衡扩展.html"> |
| |
| |
| 6.7 负载均衡扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.8" data-path="SPI参考手册/合并结果扩展.html"> |
| |
| <a href="SPI参考手册/合并结果扩展.html"> |
| |
| |
| 6.8 合并结果扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.9" data-path="SPI参考手册/注册中心扩展.html"> |
| |
| <a href="SPI参考手册/注册中心扩展.html"> |
| |
| |
| 6.9 注册中心扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.10" data-path="SPI参考手册/监控中心扩展.html"> |
| |
| <a href="SPI参考手册/监控中心扩展.html"> |
| |
| |
| 6.10 监控中心扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.11" data-path="SPI参考手册/扩展点加载扩展.html"> |
| |
| <a href="SPI参考手册/扩展点加载扩展.html"> |
| |
| |
| 6.11 扩展点加载扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.12" data-path="SPI参考手册/动态代理扩展.html"> |
| |
| <a href="SPI参考手册/动态代理扩展.html"> |
| |
| |
| 6.12 动态代理扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.13" data-path="SPI参考手册/编译器扩展.html"> |
| |
| <a href="SPI参考手册/编译器扩展.html"> |
| |
| |
| 6.13 编译器扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.14" data-path="SPI参考手册/消息派发扩展.html"> |
| |
| <a href="SPI参考手册/消息派发扩展.html"> |
| |
| |
| 6.14 消息派发扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.15" data-path="SPI参考手册/线程池扩展.html"> |
| |
| <a href="SPI参考手册/线程池扩展.html"> |
| |
| |
| 6.15 线程池扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.16" data-path="SPI参考手册/序列化扩展.html"> |
| |
| <a href="SPI参考手册/序列化扩展.html"> |
| |
| |
| 6.16 序列化扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.17" data-path="SPI参考手册/网络传输扩展.html"> |
| |
| <a href="SPI参考手册/网络传输扩展.html"> |
| |
| |
| 6.17 网络传输扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.18" data-path="SPI参考手册/信息交换扩展.html"> |
| |
| <a href="SPI参考手册/信息交换扩展.html"> |
| |
| |
| 6.18 信息交换扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.19" data-path="SPI参考手册/组网扩展.html"> |
| |
| <a href="SPI参考手册/组网扩展.html"> |
| |
| |
| 6.19 组网扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.20" data-path="SPI参考手册/Telnet命令扩展.html"> |
| |
| <a href="SPI参考手册/Telnet命令扩展.html"> |
| |
| |
| 6.20 Telnet命令扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.21" data-path="SPI参考手册/状态检查扩展.html"> |
| |
| <a href="SPI参考手册/状态检查扩展.html"> |
| |
| |
| 6.21 状态检查扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.22" data-path="SPI参考手册/容器扩展.html"> |
| |
| <a href="SPI参考手册/容器扩展.html"> |
| |
| |
| 6.22 容器扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.23" data-path="SPI参考手册/页面扩展.html"> |
| |
| <a href="SPI参考手册/页面扩展.html"> |
| |
| |
| 6.23 页面扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.24" data-path="SPI参考手册/缓存扩展.html"> |
| |
| <a href="SPI参考手册/缓存扩展.html"> |
| |
| |
| 6.24 缓存扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.25" data-path="SPI参考手册/验证扩展.html"> |
| |
| <a href="SPI参考手册/验证扩展.html"> |
| |
| |
| 6.25 验证扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.7.26" data-path="SPI参考手册/日志适配扩展.html"> |
| |
| <a href="SPI参考手册/日志适配扩展.html"> |
| |
| |
| 6.26 日志适配扩展 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| |
| </ul> |
| |
| </li> |
| |
| <li class="chapter " data-level="1.8" data-path="技术兼容性测试.html"> |
| |
| <a href="技术兼容性测试.html"> |
| |
| |
| 7 技术兼容性测试 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.9" data-path="公共契约.html"> |
| |
| <a href="公共契约.html"> |
| |
| |
| 8 公共契约 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.10" data-path="坏味道.html"> |
| |
| <a href="坏味道.html"> |
| |
| |
| 9 坏味道 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.11" data-path="编码约定.html"> |
| |
| <a href="编码约定.html"> |
| |
| |
| 10 编码约定 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.12" data-path="检查列表.html"> |
| |
| <a href="检查列表.html"> |
| |
| |
| 11 检查列表 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.13" data-path="设计原则.html"> |
| |
| <a href="设计原则.html"> |
| |
| |
| 12 设计原则 |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| |
| |
| |
| <li class="divider"></li> |
| |
| <li> |
| <a href="https://www.gitbook.com" target="blank" class="gitbook-link"> |
| Published with GitBook |
| </a> |
| </li> |
| </ul> |
| |
| |
| </nav> |
| |
| |
| </div> |
| |
| <div class="book-body"> |
| |
| <div class="body-inner"> |
| |
| |
| |
| <div class="book-header" role="navigation"> |
| |
| |
| <!-- Title --> |
| <h1> |
| <i class="fa fa-circle-o-notch fa-spin"></i> |
| <a href="." >5 扩展点加载</a> |
| </h1> |
| </div> |
| |
| |
| |
| |
| <div class="page-wrapper" tabindex="-1" role="main"> |
| <div class="page-inner"> |
| |
| <div id="book-search-results"> |
| <div class="search-noresults"> |
| |
| <section class="normal markdown-section"> |
| |
| <h4 id="扩展点配置">扩展点配置</h4> |
| <h5 id="来源:">来源:</h5> |
| <p>Dubbo的扩展点加载从JDK标准的SPI(Service Provider Interface)扩展点发现机制加强而来。</p> |
| <p>Dubbo改进了JDK标准的SPI的以下问题:</p> |
| <ul> |
| <li>JDK标准的SPI会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。</li> |
| <li>如果扩展点加载失败,连扩展点的名称都拿不到了。比如:JDK标准的ScriptEngine,通过 <code>getName()</code> 获取脚本类型的名称,但如果RubyScriptEngine因为所依赖的jruby.jar不存在,导致RubyScriptEngine类加载失败,这个失败原因被吃掉了,和ruby对应不起来,当用户执行ruby脚本时,会报不支持ruby,而不是真正失败的原因。</li> |
| <li>增加了对扩展点IoC和AOP的支持,一个扩展点可以直接setter注入其它扩展点。</li> |
| </ul> |
| <h5 id="约定:">约定:</h5> |
| <p>在扩展类的jar包内,放置扩展点配置文件:META-INF/dubbo/接口全限定名,内容为:配置名=扩展实现类全限定名,多个实现类用换行符分隔。</p> |
| <blockquote> |
| <p>注意:这里的配置文件是放在你自己的jar包内,不是dubbo本身的jar包内,Dubbo会全ClassPath扫描所有jar包内同名的这个文件,然后进行合并</p> |
| </blockquote> |
| <h5 id="扩展dubbo的协议示例:">扩展Dubbo的协议示例:</h5> |
| <p>在协议的实现jar包内放置文本文件:META-INF/dubbo/com.alibaba.dubbo.rpc.Protocol,内容为:</p> |
| <pre><code>xxx=com.alibaba.xxx.XxxProtocol |
| </code></pre><h5 id="实现类内容:">实现类内容:</h5> |
| <pre><code class="lang-java"><span class="hljs-keyword">package</span> com.alibaba.xxx; |
| |
| <span class="hljs-keyword">import</span> com.alibaba.dubbo.rpc.Protocol; |
| |
| <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">XxxProtocol</span> <span class="hljs-title">implemenets</span> <span class="hljs-title">Protocol</span> </span>{ |
| |
| <span class="hljs-comment">// ...</span> |
| |
| } |
| </code></pre> |
| <blockquote> |
| <p>注意: 扩展点使用单一实例加载(请确保扩展实现的线程安全性),Cache在 <code>ExtensionLoader</code> 中。</p> |
| </blockquote> |
| <h4 id="扩展点自动包装">扩展点自动包装</h4> |
| <h5 id="自动wrap扩展点的wrapper类">自动Wrap扩展点的Wrapper类</h5> |
| <p><code>ExtensionLoader</code> 会把加载扩展点时(通过扩展点配置文件中内容),如果该实现有拷贝构造函数,则判定为扩展点Wrapper类。Wrapper类同样实现了扩展点接口。</p> |
| <p>Wrapper类内容:</p> |
| <pre><code class="lang-java"><span class="hljs-keyword">package</span> com.alibaba.xxx; |
| |
| <span class="hljs-keyword">import</span> com.alibaba.dubbo.rpc.Protocol; |
| |
| <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">XxxProtocolWrapper</span> <span class="hljs-title">implemenets</span> <span class="hljs-title">Protocol</span> </span>{ |
| Protocol impl; |
| |
| <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">XxxProtocol</span><span class="hljs-params">(Protocol protocol)</span> </span>{ impl = protocol; } |
| |
| <span class="hljs-comment">// 接口方法做一个操作后,再调用extension的方法</span> |
| <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">refer</span><span class="hljs-params">()</span> </span>{ |
| <span class="hljs-comment">//... 一些操作</span> |
| impl.refer(); |
| <span class="hljs-comment">// ... 一些操作</span> |
| } |
| |
| <span class="hljs-comment">// ...</span> |
| } |
| </code></pre> |
| <p>Wrapper不是扩展点实现,用于从 <code>ExtensionLoader</code> 返回扩展点时,Wrap在扩展点实现外。即从 <code>ExtensionLoader</code> 中返回的实际上是Wrapper类的实例,Wrapper持有了实际的扩展点实现类。</p> |
| <p>扩展点的Wrapper类可以有多个,也可以根据需要新增。</p> |
| <p>通过Wrapper类可以把所有扩展点公共逻辑移至Wrapper中。新加的Wrapper在所有的扩展点上添加了逻辑,有些类似AOP(Wraper代理了扩展点)。</p> |
| <h4 id="扩展点自动装配">扩展点自动装配</h4> |
| <h5 id="加载扩展点时,自动注入依赖的扩展点">加载扩展点时,自动注入依赖的扩展点</h5> |
| <p>加载扩展点时,扩展点实现类的成员如果为其它扩展点类型,<code>ExtensionLoader</code> 在会自动注入依赖的扩展点。<code>ExtensionLoader</code> 通过扫描扩展点实现类的所有set方法来判定其成员。即 <code>ExtensionLoader</code> 会执行扩展点的拼装操作。</p> |
| <p>示例:有两个为扩展点 <code>CarMaker</code>(造车者)、<code>WheelMaker</code> (造轮者)</p> |
| <p>接口类如下:</p> |
| <pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">CarMaker</span> </span>{ |
| <span class="hljs-function">Car <span class="hljs-title">makeCar</span><span class="hljs-params">()</span></span>; |
| } |
| |
| <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">WheelMaker</span> </span>{ |
| <span class="hljs-function">Wheel <span class="hljs-title">makeWheel</span><span class="hljs-params">()</span></span>; |
| } |
| </code></pre> |
| <p><code>CarMaker</code> 的一个实现类:</p> |
| <pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RaceCarMaker</span> <span class="hljs-title">implemenets</span> <span class="hljs-title">CarMaker</span> </span>{ |
| WheelMaker wheelMaker; |
| |
| <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">setWheelMaker</span><span class="hljs-params">(WheelMaker wheelMaker)</span> </span>{ |
| <span class="hljs-keyword">this</span>.wheelMaker = wheelMaker; |
| } |
| |
| <span class="hljs-function"><span class="hljs-keyword">public</span> Car <span class="hljs-title">makeCar</span><span class="hljs-params">()</span> </span>{ |
| <span class="hljs-comment">// ...</span> |
| Wheel wheel = wheelMaker.makeWheel(); |
| <span class="hljs-comment">// ...</span> |
| <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> RaceCar(wheel, ...); |
| } |
| } |
| </code></pre> |
| <p><code>ExtensionLoader</code> 加载 <code>CarMaker</code> 的扩展点实现 <code>RaceCar</code> 时,<code>setWheelMaker</code> 方法的 <code>WheelMaker</code> 也是扩展点则会注入 <code>WheelMaker</code> 的实现。</p> |
| <p>这里带来另一个问题,<code>ExtensionLoader</code> 要注入依赖扩展点时,如何决定要注入依赖扩展点的哪个实现。在这个示例中,即是在多个<code>WheelMaker</code> 的实现中要注入哪个。</p> |
| <p>这个问题在下面一点 <a href="#扩展点自适应">Adaptive实例</a> 中说明。</p> |
| <h4 id="扩展点自适应">扩展点自适应</h4> |
| <p><strong>扩展点的Adaptive实例</strong> </p> |
| <p><code>ExtensionLoader</code> 注入的依赖扩展点是一个 <code>Adaptive</code> 实例,直到扩展点方法执行时才决定调用是一个扩展点实现。</p> |
| <p>Dubbo使用URL对象(包含了Key-Value)传递配置信息。</p> |
| <p>扩展点方法调用会有URL参数(或是参数有URL成员)</p> |
| <p>这样依赖的扩展点也可以从URL拿到配置信息,所有的扩展点自己定好配置的Key后,配置信息从URL上从最外层传入。URL在配置传递上即是一条总线。</p> |
| <p>示例:有两个为扩展点 <code>CarMaker</code>(造车者)、<code>WheelMaker</code> (造轮者)</p> |
| <p>接口类如下:</p> |
| <pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">CarMaker</span> </span>{ |
| <span class="hljs-function">Car <span class="hljs-title">makeCar</span><span class="hljs-params">(URL url)</span></span>; |
| } |
| |
| <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">WheelMaker</span> </span>{ |
| <span class="hljs-function">Wheel <span class="hljs-title">makeWheel</span><span class="hljs-params">(URL url)</span></span>; |
| } |
| </code></pre> |
| <p><code>CarMaker</code> 的一个实现类:</p> |
| <pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RaceCarMaker</span> <span class="hljs-title">implemenets</span> <span class="hljs-title">CarMaker</span> </span>{ |
| WheelMaker wheelMaker; |
| |
| <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">setWheelMaker</span><span class="hljs-params">(WheelMaker wheelMaker)</span> </span>{ |
| <span class="hljs-keyword">this</span>.wheelMaker = wheelMaker; |
| } |
| |
| <span class="hljs-function"><span class="hljs-keyword">public</span> Car <span class="hljs-title">makeCar</span><span class="hljs-params">(URL url)</span> </span>{ |
| <span class="hljs-comment">// ...</span> |
| Wheel wheel = wheelMaker.makeWheel(url); |
| <span class="hljs-comment">// ...</span> |
| <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> RaceCar(wheel, ...); |
| } |
| } |
| </code></pre> |
| <p>当上面执行</p> |
| <pre><code class="lang-java"><span class="hljs-comment">// ...</span> |
| Wheel wheel = wheelMaker.makeWheel(url); |
| <span class="hljs-comment">// ...</span> |
| </code></pre> |
| <p>时,注入的 <code>Adaptive</code> 实例可以提取约定Key来决定使用哪个 <code>WheelMaker</code> 实现来调用对应实现的真正的 <code>makeWheel</code> 方法。如提取 <code>wheel.type</code>, key即 <code>url.get("wheel.type")</code> 来决定 <code>WheelMake</code> 实现。<code>Adaptive</code> 实例的逻辑是固定,指定提取的URL的Key,即可以代理真正的实现类上,可以动态生成。</p> |
| <p>在Dubbo的 <code>ExtensionLoader</code> 的扩展点类开对应的 <code>Adaptive</code> 实现是在加载扩展点里动态生成。指定提取的URL的Key通过 <code>@Adaptive</code> 注解在接口方法上提供。</p> |
| <p>下面是Dubbo的Transporter扩展点的代码:</p> |
| <pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Transporter</span> </span>{ |
| <span class="hljs-meta">@Adaptive</span>({<span class="hljs-string">"server"</span>, <span class="hljs-string">"transport"</span>}) |
| <span class="hljs-function">Server <span class="hljs-title">bind</span><span class="hljs-params">(URL url, ChannelHandler handler)</span> <span class="hljs-keyword">throws</span> RemotingException</span>; |
| |
| <span class="hljs-meta">@Adaptive</span>({<span class="hljs-string">"client"</span>, <span class="hljs-string">"transport"</span>}) |
| <span class="hljs-function">Client <span class="hljs-title">connect</span><span class="hljs-params">(URL url, ChannelHandler handler)</span> <span class="hljs-keyword">throws</span> RemotingException</span>; |
| } |
| </code></pre> |
| <p>对于bind方法表示,Adaptive实现先查找"server"key,如果该Key没有值则找"transport"key值,来决定代理到哪个实际扩展点。</p> |
| <p><strong>Dubbo配置模块中扩展点的配置</strong></p> |
| <p>Dubbo配置模块中,扩展点均有对应配置属性或标签,通过配置指定使用哪个扩展实现。比如:</p> |
| <pre><code class="lang-xml"><span class="hljs-tag"><<span class="hljs-name">dubbo:protocol</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"xxx"</span> /></span> |
| </code></pre> |
| <h4 id="扩展点自动激活">扩展点自动激活</h4> |
| <p>对于集合类扩展点,比如:<code>Filter</code>, <code>InvokerListener</code>, <code>ExportListener</code>, <code>TelnetHandler</code>, <code>StatusChecker</code> 等,可以同时加载多个实现,此时,可以用自动激活来简化配置,如:</p> |
| <pre><code class="lang-java"><span class="hljs-keyword">import</span> com.alibaba.dubbo.common.extension.Activate; |
| <span class="hljs-keyword">import</span> com.alibaba.dubbo.rpc.Filter; |
| |
| <span class="hljs-meta">@Activate</span> <span class="hljs-comment">// 无条件自动激活</span> |
| <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">XxxFilter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Filter</span> </span>{ |
| <span class="hljs-comment">// ...</span> |
| } |
| </code></pre> |
| <p>或:</p> |
| <pre><code class="lang-java"><span class="hljs-keyword">import</span> com.alibaba.dubbo.common.extension.Activate; |
| <span class="hljs-keyword">import</span> com.alibaba.dubbo.rpc.Filter; |
| |
| <span class="hljs-meta">@Activate</span>(<span class="hljs-string">"xxx"</span>) <span class="hljs-comment">// 当配置了xxx参数,并且参数为有效值时激活,比如配了cache="lru",自动激活CacheFilter。</span> |
| <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">XxxFilter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Filter</span> </span>{ |
| <span class="hljs-comment">// ...</span> |
| } |
| </code></pre> |
| <p>或:</p> |
| <pre><code class="lang-java"><span class="hljs-keyword">import</span> com.alibaba.dubbo.common.extension.Activate; |
| <span class="hljs-keyword">import</span> com.alibaba.dubbo.rpc.Filter; |
| |
| <span class="hljs-meta">@Activate</span>(group = <span class="hljs-string">"provider"</span>, value = <span class="hljs-string">"xxx"</span>) <span class="hljs-comment">// 只对提供方激活,group可选"provider"或"consumer"</span> |
| <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">XxxFilter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Filter</span> </span>{ |
| <span class="hljs-comment">// ...</span> |
| } |
| </code></pre> |
| |
| |
| </section> |
| |
| </div> |
| <div class="search-results"> |
| <div class="has-results"> |
| |
| <h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1> |
| <ul class="search-results-list"></ul> |
| |
| </div> |
| <div class="no-results"> |
| |
| <h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1> |
| |
| </div> |
| </div> |
| </div> |
| |
| </div> |
| </div> |
| |
| </div> |
| |
| |
| |
| <a href="框架设计.html" class="navigation navigation-prev " aria-label="Previous page: 4 框架设计"> |
| <i class="fa fa-angle-left"></i> |
| </a> |
| |
| |
| <a href="SPI参考手册/introduction.html" class="navigation navigation-next " aria-label="Next page: 6 SPI参考手册"> |
| <i class="fa fa-angle-right"></i> |
| </a> |
| |
| |
| |
| </div> |
| |
| <script> |
| var gitbook = gitbook || []; |
| gitbook.push(function() { |
| gitbook.page.hasChanged({"page":{"title":"5 扩展点加载","level":"1.6","depth":1,"next":{"title":"6 SPI参考手册","level":"1.7","depth":1,"path":"SPI参考手册/introduction.md","ref":"./SPI参考手册/introduction.md","articles":[{"title":"6.1 协议扩展","level":"1.7.1","depth":2,"path":"SPI参考手册/协议扩展.md","ref":"./SPI参考手册/协议扩展.md","articles":[]},{"title":"6.2 调用拦截扩展","level":"1.7.2","depth":2,"path":"SPI参考手册/调用拦截扩展.md","ref":"./SPI参考手册/调用拦截扩展.md","articles":[]},{"title":"6.3 引用监听扩展","level":"1.7.3","depth":2,"path":"SPI参考手册/引用监听扩展.md","ref":"./SPI参考手册/引用监听扩展.md","articles":[]},{"title":"6.4 暴露监听扩展","level":"1.7.4","depth":2,"path":"SPI参考手册/暴露监听扩展.md","ref":"./SPI参考手册/暴露监听扩展.md","articles":[]},{"title":"6.5 集群扩展","level":"1.7.5","depth":2,"path":"SPI参考手册/集群扩展.md","ref":"./SPI参考手册/集群扩展.md","articles":[]},{"title":"6.6 路由扩展","level":"1.7.6","depth":2,"path":"SPI参考手册/路由扩展.md","ref":"./SPI参考手册/路由扩展.md","articles":[]},{"title":"6.7 负载均衡扩展","level":"1.7.7","depth":2,"path":"SPI参考手册/负载均衡扩展.md","ref":"./SPI参考手册/负载均衡扩展.md","articles":[]},{"title":"6.8 合并结果扩展","level":"1.7.8","depth":2,"path":"SPI参考手册/合并结果扩展.md","ref":"./SPI参考手册/合并结果扩展.md","articles":[]},{"title":"6.9 注册中心扩展","level":"1.7.9","depth":2,"path":"SPI参考手册/注册中心扩展.md","ref":"./SPI参考手册/注册中心扩展.md","articles":[]},{"title":"6.10 监控中心扩展","level":"1.7.10","depth":2,"path":"SPI参考手册/监控中心扩展.md","ref":"./SPI参考手册/监控中心扩展.md","articles":[]},{"title":"6.11 扩展点加载扩展","level":"1.7.11","depth":2,"path":"SPI参考手册/扩展点加载扩展.md","ref":"./SPI参考手册/扩展点加载扩展.md","articles":[]},{"title":"6.12 动态代理扩展","level":"1.7.12","depth":2,"path":"SPI参考手册/动态代理扩展.md","ref":"./SPI参考手册/动态代理扩展.md","articles":[]},{"title":"6.13 编译器扩展","level":"1.7.13","depth":2,"path":"SPI参考手册/编译器扩展.md","ref":"./SPI参考手册/编译器扩展.md","articles":[]},{"title":"6.14 消息派发扩展","level":"1.7.14","depth":2,"path":"SPI参考手册/消息派发扩展.md","ref":"./SPI参考手册/消息派发扩展.md","articles":[]},{"title":"6.15 线程池扩展","level":"1.7.15","depth":2,"path":"SPI参考手册/线程池扩展.md","ref":"./SPI参考手册/线程池扩展.md","articles":[]},{"title":"6.16 序列化扩展","level":"1.7.16","depth":2,"path":"SPI参考手册/序列化扩展.md","ref":"./SPI参考手册/序列化扩展.md","articles":[]},{"title":"6.17 网络传输扩展","level":"1.7.17","depth":2,"path":"SPI参考手册/网络传输扩展.md","ref":"./SPI参考手册/网络传输扩展.md","articles":[]},{"title":"6.18 信息交换扩展","level":"1.7.18","depth":2,"path":"SPI参考手册/信息交换扩展.md","ref":"./SPI参考手册/信息交换扩展.md","articles":[]},{"title":"6.19 组网扩展","level":"1.7.19","depth":2,"path":"SPI参考手册/组网扩展.md","ref":"./SPI参考手册/组网扩展.md","articles":[]},{"title":"6.20 Telnet命令扩展","level":"1.7.20","depth":2,"path":"SPI参考手册/Telnet命令扩展.md","ref":"./SPI参考手册/Telnet命令扩展.md","articles":[]},{"title":"6.21 状态检查扩展","level":"1.7.21","depth":2,"path":"SPI参考手册/状态检查扩展.md","ref":"./SPI参考手册/状态检查扩展.md","articles":[]},{"title":"6.22 容器扩展","level":"1.7.22","depth":2,"path":"SPI参考手册/容器扩展.md","ref":"./SPI参考手册/容器扩展.md","articles":[]},{"title":"6.23 页面扩展","level":"1.7.23","depth":2,"path":"SPI参考手册/页面扩展.md","ref":"./SPI参考手册/页面扩展.md","articles":[]},{"title":"6.24 缓存扩展","level":"1.7.24","depth":2,"path":"SPI参考手册/缓存扩展.md","ref":"./SPI参考手册/缓存扩展.md","articles":[]},{"title":"6.25 验证扩展","level":"1.7.25","depth":2,"path":"SPI参考手册/验证扩展.md","ref":"./SPI参考手册/验证扩展.md","articles":[]},{"title":"6.26 日志适配扩展","level":"1.7.26","depth":2,"path":"SPI参考手册/日志适配扩展.md","ref":"./SPI参考手册/日志适配扩展.md","articles":[]}]},"previous":{"title":"4 框架设计","level":"1.5","depth":1,"path":"框架设计.md","ref":"./框架设计.md","articles":[]},"dir":"ltr"},"config":{"gitbook":"*","theme":"default","variables":{},"plugins":[],"pluginsConfig":{"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"}},"file":{"path":"扩展点加载.md","mtime":"2017-07-24T03:22:54.000Z","type":"markdown"},"gitbook":{"version":"3.2.2","time":"2017-07-28T06:06:03.101Z"},"basePath":".","book":{"language":""}}); |
| }); |
| </script> |
| </div> |
| |
| |
| <script src="gitbook/gitbook.js"></script> |
| <script src="gitbook/theme.js"></script> |
| |
| |
| <script src="gitbook/gitbook-plugin-search/search-engine.js"></script> |
| |
| |
| |
| <script src="gitbook/gitbook-plugin-search/search.js"></script> |
| |
| |
| |
| <script src="gitbook/gitbook-plugin-lunr/lunr.min.js"></script> |
| |
| |
| |
| <script src="gitbook/gitbook-plugin-lunr/search-lunr.js"></script> |
| |
| |
| |
| <script src="gitbook/gitbook-plugin-sharing/buttons.js"></script> |
| |
| |
| |
| <script src="gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script> |
| |
| |
| |
| </body> |
| </html> |
| |