<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="https://blog.ccoder.cc/atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-CN">
  <id>https://blog.ccoder.cc/</id>
  <title>聪聪碎碎念</title>
  <subtitle>聪聪碎碎念 — Java 后端开发工程师的技术博客，专注支付行业、分布式系统、面试经验分享</subtitle>
  <icon>https://blog.ccoder.cc/favicon.ico</icon>
  <updated>2026-07-09T05:12:15.797Z</updated>
  <generator>@vuepress/plugin-feed</generator>
  <link rel="self" href="https://blog.ccoder.cc/atom.xml"/>
  <link rel="alternate" href="https://blog.ccoder.cc/"/>
  <category term="旅途"/>
  <category term="Dubbo"/>
  <category term="课题研究"/>
  <category term="面试"/>
  <category term="支付"/>
  <category term="Java"/>
  <category term="DDD"/>
  <category term="Go"/>
  <category term="清算知识"/>
  <category term="MySQL"/>
  <contributor>
    <name>聪聪</name>
  </contributor>
  <entry>
    <title type="text">模板文件template</title>
    <id>https://blog.ccoder.cc/notes/template.html</id>
    <link href="https://blog.ccoder.cc/notes/template.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <author>
      <name>聪聪</name>
    </author>
    <category term="旅途"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2022-07-29T10:49:10.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">Dubbo-ExtensionLoader</title>
    <id>https://blog.ccoder.cc/posts/2021/Dubbo-ExtensionLoader.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/Dubbo-ExtensionLoader.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>[TOC]</p>
<h2>扩展点加载机制</h2>
<blockquote>
<p>Dubbo的扩展点加载来自于JDK的标准SPI(Service Provider Interface)扩展点发现机制，并对其进行加强。</p>
</blockquote>
<p>来自Dubbo官网的描述，Dubbo改进了JDK标准SPI，并且解决了一下问题:</p>
<ul>
<li>JDK标准的SPI会一次性实例化扩展点所有实现，如果扩展实现初始化很耗时，但如果没有用上也加载就会很浪费资源。</li>
<li>如果扩展点加载失败，连扩展点的名称都拿不到了。</li>
<li>增加了对扩展点的IoC和AOP的支持，一个扩展点可以直接setter注入其他扩展点。</li>
</ul>]]></summary>
    <content type="html"><![CDATA[<p>[TOC]</p>
<h2>扩展点加载机制</h2>
<blockquote>
<p>Dubbo的扩展点加载来自于JDK的标准SPI(Service Provider Interface)扩展点发现机制，并对其进行加强。</p>
</blockquote>
<p>来自Dubbo官网的描述，Dubbo改进了JDK标准SPI，并且解决了一下问题:</p>
<ul>
<li>JDK标准的SPI会一次性实例化扩展点所有实现，如果扩展实现初始化很耗时，但如果没有用上也加载就会很浪费资源。</li>
<li>如果扩展点加载失败，连扩展点的名称都拿不到了。</li>
<li>增加了对扩展点的IoC和AOP的支持，一个扩展点可以直接setter注入其他扩展点。</li>
</ul>
<p>Dubbo约定在扩展类的jar包内，放置扩展点配置文件<code>META-INF/dubbo/接口全限定名</code>，内容为：<code>配置名=扩展实现类全限定名</code>，存在多个实现类时用换行符分割。</p>
<h2>简单介绍Java SPI机制</h2>
<blockquote>
<p>SPI ，全称为Service Provider Interface, 是一种服务发现机制。它通过在<code>ClassPath</code>路径下的<code>META-INF/service</code>查找并自动加载实现类。</p>
<p>简单来说就是一种动态替换发现机制，接口运行时才发现具体的实现类，只需要在运行前添加一个实现即可，并且将实现<strong>描述</strong>给JDK即可，这里的描述便是上面提到的<code>META-INF/service</code>下的配置。也可以随时对该描述进行修改，完成具体实现的替换。</p>
</blockquote>
<p>Java提供了很多SPI，允许第三方为这些接口提供实现；常见的SPI有JDBC、JNDI等。</p>
<p>这些SPI接口是由Java来提供的，而SPI的实现则是作为依赖的第三方jar加载进<code>CLASSPATH</code>zhong .</p>
<p>例如：Java提供的<code>java.sql.Driver</code>和MySql实现的<code>com.mysql.cj.jdbc.Driver</code>，并且在<code>META-INF/service</code>下存在该配置:<code>com.mysql.cj.jdbc.Driver</code></p>
<h3>写个Demo实现看看</h3>
<p>下面简单写个Demo实现看看：</p>
<ol>
<li>
<p>我们先提供一个接口</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#383A42;--shiki-dark:#C678DD"> cc.ccoder.loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> interface</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DownloadStrategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> download</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></li>
<li>
<p>分别提供两个实现类，这两个实现类可以理解成第三方jar中对标准接口的实现。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#383A42;--shiki-dark:#C678DD"> cc.ccoder.loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> HttpDownloadStrategy</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> implements</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DownloadStrategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#A626A4;--shiki-dark:#E5C07B">Override</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> download</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        System</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">out</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">println</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"采用Http下载方式"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#383A42;--shiki-dark:#C678DD"> cc.ccoder.loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> SftpDownloadStrategy</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> implements</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DownloadStrategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#A626A4;--shiki-dark:#E5C07B">Override</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> download</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        System</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">out</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">println</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"采用SFTP方式下载"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></li>
<li>
<p>在<code>META-INF/services</code>目录下创建一个扩展点配置文件，路径为<code>META-INF/services/接口全限定名称</code>。那么我们这个例子的文件名称是<code>cc.ccoder.loader.DownloadStrategy</code> 并且文件名内容为具体实现类全限定名称。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">cc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ccoder</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">HttpDownloadStrategy</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">cc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ccoder</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">SftpDownloadStrategy</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div></li>
<li>
<p>写一个测试类通过<code>ServiceLoader</code>加载具体的实现</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#383A42;--shiki-dark:#C678DD"> cc.ccoder.loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> java.util.ServiceLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> JavaSpiLoaderTest</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[] </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        ServiceLoader</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">DownloadStrategy</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">> </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">serviceLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> ServiceLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">load</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">DownloadStrategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //这里会一次实例化所有接口实现</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">DownloadStrategy</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> downloadStrategy</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> :</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> serviceLoader) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            downloadStrategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">download</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></li>
<li>
<p>看看输出结果</p>
<p>和我们预期一样，会一次实例化所所有接口实现。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Connected</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> to the target VM</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> address</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> '127.0.0.1:64219'</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> transport</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 'socket'</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">采用Http下载方式</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">采用SFTP方式下载</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Disconnected</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> from the target VM</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> address</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> '127.0.0.1:64219'</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> transport</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 'socket'</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Process</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> finished with exit code </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></li>
</ol>
<h2>普通扩展点加载</h2>
<p>上面提到了Java的SPI机制，那么Dubbo的<code>ExtensionLoader</code>则是对SPI的加强。这里我们改造一下上面那个例子并且写一个测试看看。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#383A42;--shiki-dark:#C678DD"> cc.ccoder.loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> org.apache.dubbo.common.extension.SPI</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#A626A4;--shiki-dark:#E5C07B">SPI</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"http"</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> interface</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DownloadStrategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> download</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在<code>DownloadStrategy</code>接口上添加<code>@SPI</code>注解。</p>
<p>修改<code>META-INF/services</code>的配置文件</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">http</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">cc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ccoder</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">HttpDownloadStrategy</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">sftp</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">cc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ccoder</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">SftpDownloadStrategy</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>运行一下测试方法</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#383A42;--shiki-dark:#C678DD"> cc.ccoder.loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> org.apache.dubbo.common.extension.ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DubboSpiLoaderTest</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[] </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        ExtensionLoader</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">DownloadStrategy</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">> </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">extensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">DownloadStrategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //这里getExtension方法进行加载具体扩展点</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        DownloadStrategy</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> downloadStrategy</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> extensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"http"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        downloadStrategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">download</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">采用Http下载方式</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Process</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> finished with exit code </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>从获取扩展点的方式我们可以发现，dubbo扩展点是获取具体的实例，并不需要实例化所有的实现类。</p>
<h3>getExtensionLoader</h3>
<p>从示例中我们了解到从<code>ExtensionLoader.getExtensionLoader</code>方法中可以看到类似于工厂方法，获取扩展点的Extension，再通过调用<code>getExtension</code>方法传入指定的名字即可获取到指定的扩展点实现类。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> static</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> &#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">T</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">T</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">T</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> type) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (type </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalArgumentException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Extension type == null"</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isInterface</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalArgumentException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Extension type ("</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> type </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ") is not an interface!"</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">withExtensionAnnotation</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(type)) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalArgumentException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Extension type ("</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> type </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">                    ") is not an extension, because it is NOT annotated with @"</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> SPI</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getSimpleName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "!"</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // 查看本地是否存在扩展点类型的Loader</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // 创建一个ExtensionLoader 并且将ExtensionFactory 的实现类均放入这个EXTENSION_LOADERS的本地map缓存中</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // ExtensionFactory 的实现有SpiExtensionFactory 和 SpringExtensionFactory</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        ExtensionLoader</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">T</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> loader </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">T</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">EXTENSION_LOADERS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(type);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (loader </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            EXTENSION_LOADERS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">putIfAbsent</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(type, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">new</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>(type));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            loader </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">T</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">EXTENSION_LOADERS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(type);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><img src="https://tva1.sinaimg.cn/large/008i3skNgy1gsnlg4wo9tj30te07x0u6.jpg" alt="image-20210720183149860" loading="lazy"></p>
<h3>getExtension</h3>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(name)</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">    -></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> createExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(name) #缓存获取 无缓存则创建</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">        -></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getExtensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> #从缓存中获取name的扩展点类型</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">        -></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> 实例化扩展类</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">        -></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> injectExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(instance) # 扩展点IOC注入</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">        -></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> injectExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">((T) </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">wrapperClass</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getConstructor</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(type).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">newInstance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(instance)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) </span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">  #循环遍历所有wrapper实现，实例化wrapper并进行扩展点IOC注入</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>获取Dubbo的扩展点就从这个方法<code>ExtensionLoader.getExtension(String name)</code>出发吧。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> boolean</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> wrap) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">StringUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isEmpty</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalArgumentException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Extension name == null"</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //如果传入的name为字符串true 则返回默认的扩展点</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"true"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">equals</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getDefaultExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //从缓存中获取Holder 不存在则创建该缓存对象 并且从缓存中拿，可以防止放入缓存中失败的情况、</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //dubbo 实际将扩展类封装在Holder类中</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        final</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Holder</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> holder </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getOrCreateHolder</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(name)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Object</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> holder</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //double-check 保证线程安全</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            synchronized</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (holder) {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> holder</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //缓存中没有就创建该扩展点</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> createExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> wrap)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //放入缓存 下次直接从缓存中拿取</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    holder</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">set</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(instance);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (T) instance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在上述<code>getDefaultExtension()</code>方法主要是去拿默认扩展点名称，在load所有扩展点的方法里，会判断<code>@SPI</code>中的value值，即为默认的扩展点名称，将会赋值给<code>cachedDefaultName</code>，所以这里可以拿到一个默认扩展类。</p>
<h3>createExtension</h3>
<p>接下来看看<code>createExtension(String name,boolean wrap)</code>方法如何创建扩展点。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> createExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> boolean</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> wrap) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //name:spi 获取到SpiExtensionFactory</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Class</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> clazz </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getExtensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (clazz </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> unacceptableExceptions</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">contains</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> findException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(name)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        try</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //加载本地缓存Map(SpringExtensionFactory. SpiExtensionFactory)中的SpiExtensionFactory</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">            T</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (T) </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">EXTENSION_INSTANCES</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(clazz);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //name:spi clazz:SpiExtensionFactory 这里反射将其加载到缓存中</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                EXTENSION_INSTANCES</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">putIfAbsent</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(clazz, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getDeclaredConstructor</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">newInstance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (T) </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">EXTENSION_INSTANCES</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(clazz);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //IOC注入</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            injectExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(instance)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (wrap) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //包装类装饰</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                List</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Class</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">>></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> wrapperClassesList </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> ArrayList</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (cachedWrapperClasses </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    wrapperClassesList</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">addAll</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(cachedWrapperClasses);</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    wrapperClassesList</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sort</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">WrapperComparator</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">COMPARATOR</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    Collections</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">reverse</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(wrapperClassesList);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">CollectionUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isNotEmpty</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(wrapperClassesList)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    for</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Class</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> wrapperClass </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> wrapperClassesList) {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                        Wrapper</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> wrapper </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> wrapperClass</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getAnnotation</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">Wrapper</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (wrapper </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">                                ||</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ArrayUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">contains</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">wrapper</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">matches</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), name)</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> !</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ArrayUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">contains</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">wrapper</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">mismatches</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), name)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)) {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                            instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> injectExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">((T) </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">wrapperClass</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getConstructor</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(type).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">newInstance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(instance)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            initExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(instance)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> instance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">catch</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Throwable</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> t</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Extension instance (name: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> name </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ", class: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    type </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ") couldn't be instantiated: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> t)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul>
<li>IoC注入：在上面注释中提到有一个<code>ExtensionFactory</code>，<code>injectExtension</code>方法可以将扩展点中需要注入的依赖去<code>ExtensionFactory</code>中找到，并且赋值。</li>
<li>包装类装饰：这里有一个<code>cachedWrapperClasses</code>变量，不为空则会遍历，并且拿到具体Class对象的构造器，将刚刚反射创建的扩展点包装进来，并且进行Ioc依赖。</li>
</ul>
<h3>getExtensionClasses</h3>
<p>继续看上面的关键方法<code>getExtensionClasses()</code> 寻找扩展点</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Map</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">>></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getExtensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //缓存加载</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Map</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">>></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> classes </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> cachedClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (classes </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //double-check</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            synchronized</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (cachedClasses) {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                classes </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> cachedClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (classes </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //关键方法:获取所有扩展点 </span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    classes </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> loadExtensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    cachedClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">set</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(classes);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> classes</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>根据我们上面的示例，这里在<code>loadExtensionClasses()</code>方法加载完后，classes变量应该有两个值,key-name,value-class的形式存在，分别为：</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"http"</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD"> -></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {Class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#A626A4;--shiki-dark:#E5C07B">1390</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">} </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"class cc.ccoder.loader.HttpDownloadStrategy"</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"sftp"</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD"> -></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {Class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#A626A4;--shiki-dark:#E5C07B">1391</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">} </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"class cc.ccoder.loader.SftpDownloadStrategy"</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h3>loadExtensionClasses</h3>
<p>然后继续查看关键方法<code>loadExtensionClasses()</code></p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Map</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">>></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> loadExtensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //获取扩展点上的@SPI注解 并且缓存默认扩展点名称</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        cacheDefaultExtensionName</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //所有扩展点放入缓存</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Map</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">>></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> extensionClasses </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> HashMap</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //加载策略  这里是一个工厂方法;对指定文件夹进行加载</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //DubboInternalLoadingStrategy => META-INF/dubbo/internal/</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //DubboLoadingStrategy => META-INF/dubbo/</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //ServicesLoadingStrategy => META-INF/services/</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">LoadingStrategy</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> strategy </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> strategies) {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            loadDirectory</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> strategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">directory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> strategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">preferExtensionClassLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    strategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">overridden</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> strategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">excludedPackages</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            loadDirectory</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> strategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">directory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">replace</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"org.apache"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"com.alibaba"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">),</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    strategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">preferExtensionClassLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> strategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">overridden</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> strategy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">excludedPackages</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>之前版本的的加载时直接对这几个文件夹进行<code>loadingDirectory</code>，重新调整后通过工厂方法类，UML如下：</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">loadDirectory</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> DUBBO_INTERNAL_DIRECTORY</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">loadDirectory</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> DUBBO_INTERNAL_DIRECTORY</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">replace</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"org.apache"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"com.alibaba"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">loadDirectory</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> DUBBO_DIRECTORY</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">loadDirectory</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> DUBBO_DIRECTORY</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">replace</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"org.apache"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"com.alibaba"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">loadDirectory</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> SERVICES_DIRECTORY</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">loadDirectory</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> SERVICES_DIRECTORY</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">replace</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"org.apache"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"com.alibaba"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><img src="https://tva1.sinaimg.cn/large/008i3skNgy1gsnmkm6ngnj31fo0iuwha.jpg" alt="image-20210720191055545" loading="lazy"></p>
<h3>cachedDefaultExtensionName</h3>
<p>继续主线往下看，接下来就需要看看<code>cachedDefaultExtensionName()</code>方法做了哪些事情</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">   /**</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * extract and cache default extension name if exists</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     */</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> cacheDefaultExtensionName</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //拿到@SPI注解</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        final</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> SPI</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> defaultAnnotation </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getAnnotation</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">SPI</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (defaultAnnotation </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //拿到@SPI注解的value</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> value </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> defaultAnnotation</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">value</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> ((value </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> value</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">trim</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">length</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">            String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">[] names </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> NAME_SEPARATOR</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">split</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(value);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //从这里可以看到默认扩展点只能够这只一个</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">names</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">length</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"More than 1 default extension name on extension "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">                        +</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ": "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> Arrays</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">toString</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(names)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">names</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">length</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //将这个值复制给cachedDefaultName</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                cachedDefaultName </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> names[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">]</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里加载默认扩展点就和之前的相对应上，默认扩展点的加载时会获取@SPI注解的value,将其赋值给<code>cachedDefaultName</code>变量，在获取默认扩展点时，检查此变量并且从缓存中获取到默认扩展点。</p>
<h3>loadDirectory</h3>
<p>然后继续回到上面<code>loadDirectory</code>方法会这三个路径下的文件进行加载，我们的配置文件以扩展接口全限定名称作为文件名放入以上三个相对路径其中之一即可，即可被<code>loadingDirectory</code>方法加载读取到。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">private</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> loadDirectory</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Map</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">>></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> dir</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                               boolean</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> extensionLoaderClassLoaderFirst</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> boolean</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> overridden</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">...</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> excludedPackages</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //将相对路径和全限定类名作为文件路径</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //例如: META-INF/services/cc.ccoder.loader.HttpDownloadStrategy</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> fileName </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> dir </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        try</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">            Enumeration</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">java</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">net</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">URL</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> urls </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">            ClassLoader</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> classLoader </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> findClassLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // try to load from ExtensionLoader's ClassLoader first</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //首先尝试从ExtensionLoader的类加载器加载 该属性在LoaderStrategy接口中是一个默认方法并且为false</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (extensionLoaderClassLoaderFirst) {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                ClassLoader</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> extensionLoaderClassLoader </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getClassLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ClassLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getSystemClassLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> !=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> extensionLoaderClassLoader) {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    urls </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> extensionLoaderClassLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getResources</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fileName);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (urls </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> !</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">urls</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">hasMoreElements</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (classLoader </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //根据文件路径获取文件</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    urls </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> classLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getResources</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fileName);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    urls </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> ClassLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getSystemResources</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fileName);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (urls </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                while</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">urls</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">hasMoreElements</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //对文件中内容 进行逐条加载资源</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                    java</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">net</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">URL</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> resourceURL </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> urls</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">nextElement</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                    loadResource</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> classLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> resourceURL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> overridden</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> excludedPackages)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">catch</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Throwable</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> t</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            logger</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">error</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Exception occurred when loading extension class (interface: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    type </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ", description file: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> fileName </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ")."</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, t);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>loadResource</h3>
<p>上面<code>loadDirectory</code>方法会依次读取配置文件中扩展点配置，并且执行方法<code>loadResource</code>方法进行加载资源。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">private</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> loadResource</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Map</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">>></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> ClassLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> classLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                              java</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">net</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">URL</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> resourceURL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> boolean</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> overridden</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">...</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> excludedPackages</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        try</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //创建流 准备读取文件中内容</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            try</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">BufferedReader</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> reader </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> BufferedReader</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> InputStreamReader</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">resourceURL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">openStream</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> StandardCharsets</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">UTF_8</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">))) {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> line</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> clazz </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                while</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> ((line </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> reader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">readLine</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //定位符# 过滤掉文件中的注释内容</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    final</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> ci </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> line</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">indexOf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">'#'</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (ci </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">>=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                        line </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> line</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">substring</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, ci);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    line </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> line</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">trim</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">line</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">length</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                        try</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                            String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> name </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                            //定位符 = ,这是正式的记录 并且以=进行分割</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                            int</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> i </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> line</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">indexOf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">'='</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (i </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                                // = 左边的为name</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                                // = 右边的为class,扩展点的全限定类名</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                                name </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> line</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">substring</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, i).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">trim</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                                clazz </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> line</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">substring</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(i </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">trim</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                            } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                                // 当然也可以为空 直接整行记录为扩展点的全限定类名</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                                clazz </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> line</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">StringUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isNotEmpty</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(clazz)</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> !</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isExcluded</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> excludedPackages)) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                                //加载类，利用反射预加载上面读取到的全限定类名</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                                loadClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> resourceURL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">forName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(clazz, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">true</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, classLoader),</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> overridden)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">catch</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Throwable</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> t</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                            IllegalStateException</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> e </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">                                    "Failed to load extension class (interface: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> type </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ", class line: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> line </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ") in "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> resourceURL </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">                                            ", cause: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> t)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                            exceptions</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">put</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(line, e);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">catch</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Throwable</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> t</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            logger</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">error</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Exception occurred when loading extension class (interface: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    type </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ", class file: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> resourceURL </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ") in "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> resourceURL, t);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里就是利用文件流进行读取配置文件，并且过滤注释(#), 逐行读取并且解析分割name和class内容，然后进行<code>loadClass</code>方法加载获取的全限定类名和名称，将其缓存到<code>extensionClasses</code>中。</p>
<h3>loadClass</h3>
<p>接下来重点是<code>loadClass</code>这个方法</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">   private</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> loadClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Map</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">>></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> java</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">net</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">URL</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> resourceURL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                           boolean</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> overridden) throws NoSuchMethodException {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //扩展类对象必须是扩展点接口的子类</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isAssignableFrom</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(clazz)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Error occurred when loading extension class (interface: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    type </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ", class line: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "), class "</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">                    +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> " is not subtype of interface."</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //自适应扩展点</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isAnnotationPresent</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">Adaptive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //将cachedWrapperClasses变量设置为clazz</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            cacheAdaptiveClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> overridden)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isWrapperClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(clazz)) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //判断扩展点构造函数中是否有参数是当前扩展接口类型</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //如果有，则为包装装饰类，将cachedWrapperClasses变量添加到当前clazz</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            cacheWrapperClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(clazz)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //此处为普通的扩展点</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //获取默认的构造函数，没有默认构造函数则抛出异常</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getConstructor</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">StringUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isEmpty</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //如果name为空 则判断类上是否存在@Extension注解，并且该注解的value为name =>extension.value</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //没有此注解则以小写类名为name =>clazz.getSimpleName()</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                name </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> findAnnotationName</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(clazz)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">length</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">                            "No such extension name for the class "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> " in the config "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> resourceURL)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">            String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">[] names </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> NAME_SEPARATOR</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">split</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ArrayUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isNotEmpty</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(names)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //如果类中有@Activate注解，则将name与注解对象缓存在cacheActivateClass变量中 cachedActivates.put(name, activate)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                cacheActivateClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> names[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">])</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                for</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> n </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> names) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //缓存name key:clazz, value:name cachedNames.put(clazz, name);</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                    cacheName</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> n)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //最后将拿到的扩展类放入map中 extensionClasses.put(name, clazz);</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                    saveInExtensionClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> n</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> overridden)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在<code>saveInExtensionClass</code>方法中如果扩展点作为普通扩展点，则将其放入<code>extensionClasses</code>中，以便后面取用。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    /**</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * put clazz in extensionClasses</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     */</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> saveInExtensionClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Map</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">>></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> boolean</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> overridden) {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Class</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> c </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (c </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> overridden) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //放入extensionClasses</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            extensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">put</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name, clazz);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (c </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> clazz) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // duplicate implementation is unacceptable</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            unacceptableExceptions</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">add</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name);</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">            String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> duplicateMsg </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">                    "Duplicate extension "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> " name "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> name </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> " on "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> c</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> " and "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> clazz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            logger</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">error</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(duplicateMsg);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(duplicateMsg)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>现在我们就可以回忆一下，<code>@SPI</code>扩展点的获取基本完成，并且从<code>loadClass</code>中发现只有普通扩展点才会被放入<code>extensionClasses</code>中。</p>
<ul>
<li>如果类中有<code>@Adaptive</code>注解，则将clazz放入<code>cachedAdaptiveClass</code>变量中，表示此类为自适应扩展类</li>
<li>如果类的函数参数是扩展点接口类型的，将其将入<code>cachedWrapperClasses</code>变量，表示此类为包装装饰类</li>
<li>如果上述两点都不满足，代表此类为普通扩展类，将其放入<code>extensionClasses</code>中，后续从该Map中获取。</li>
</ul>
<p>一般来说扩展点都是普通扩展点，我们可以从<code>extensionClasses</code>中取用，那么就可以会到<code>createExtension</code>方法中从这个map中使用name拿取clazz对象，利用反射实例化进行使用。<code>Class&lt;?&gt; clazz = getExtensionClasses().get(name);</code></p>
<h3>IOC依赖注入机制</h3>
<p>上面<code>createExtension</code>方法中提到了<code>injectExtension(instance)进行注入。在获得扩展类时并不是简单的返回扩展类对象，而是会调用该方法后再进行返回，</code>并且在包装类中也会调用此方法注入依赖再进行返回。那么就来看看<code>injectExtension(instance)</code>方法都做了哪些事情。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">   private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> injectExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">T</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> instance) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //objectFactory 是ExtensionFactory 的变量，在类构造器根据自适应扩展点进行初始化</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //类似于IOC容器工厂 实现的有SpiExtensionFactory SpringExtensionFactory</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (objectFactory </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> instance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        try</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //反射遍历实例中所有的方法</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            for</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Method</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> method </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> instance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getClass</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getMethods</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //判断是否为setter方法:</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //方法名以set开头 startWith('set')</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                // 方法参数只有一个 getParameterTypes.length()==1</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                // 方法为public类型 Modifier.isPublic</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isSetter</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(method)) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    continue</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                /**</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                 * Check {@link DisableInject} to see if we need auto injection for this property</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                 */</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //判断校验该属性是否需要自动注入</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //打上了@DisableInject注解则不需要注入操作</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">method</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getAnnotation</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">DisableInject</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> !=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    continue</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //获取该方法参数的clazz</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                Class</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> pt </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> method</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getParameterTypes</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">]</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ReflectUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isPrimitives</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(pt)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    continue</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                try</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //获取方法名中需要注入的属性property</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //例如:方法setVersion 获取属性为version 并且将第四个小写 便是version</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                    String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> property </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getSetterProperty</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(method)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                    //使用参数的clazz与参数名称去ExtensionFactory 的 IOC容器中拿取扩展点类</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                    Object</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> object </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> objectFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(pt, property);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (object </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                        //调用set方法，完成注入</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                        method</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">invoke</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(instance, object);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">catch</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Exception</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> e</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    logger</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">error</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Failed to inject via method "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> method</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">                            +</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> " of interface "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ": "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> e</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), e);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">catch</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Exception</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> e</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            logger</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">error</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">e</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), e);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> instance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>上述方法阅读完后可以总结如下：</p>
<ul>
<li>方法需要是set开头，参数为需要注入的依赖类型</li>
<li>此方法若被<code>@DisableInject</code>标记，则不需要进行注入</li>
<li>上面<code>ExtensionFactory</code>的IOC容器<code>objectFactory</code>是如何获取到扩展点的，便是下面的自适应扩展机制。</li>
</ul>
<h3>包装类装饰</h3>
<p>从上面<code>loadClass</code>中发现，当我们获取扩展类时，如果有的类是包装类，那么此类并不会放<code>extensionClasses</code>类中被获取，而是放入<code>cachedWrapperClasses</code>中，在返回扩展示例的时候包装其他扩展示例。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (wrap) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //包装类装饰</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                List</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Class</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">>></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> wrapperClassesList </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> ArrayList</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (cachedWrapperClasses </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    wrapperClassesList</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">addAll</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(cachedWrapperClasses);</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    wrapperClassesList</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sort</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">WrapperComparator</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">COMPARATOR</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    Collections</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">reverse</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(wrapperClassesList);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //前面提到在loadClass中如果扩展类时包装装饰类,便会将其放入cachedWrapperClasses 那么此处wrapperClassList也不会为空</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">CollectionUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isNotEmpty</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(wrapperClassesList)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    for</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Class</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> wrapperClass </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> wrapperClassesList) {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                        Wrapper</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> wrapper </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> wrapperClass</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getAnnotation</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">Wrapper</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (wrapper </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">                                ||</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ArrayUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">contains</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">wrapper</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">matches</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), name)</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> !</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ArrayUtils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">contains</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">wrapper</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">mismatches</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), name)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                            //在此处进行注入包装</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                            //同样利用反射创建此包装扩展点的实例，并将普通扩展点作为构造器参数传入包装扩展点进行实例化，此时返回的是包装器扩展点</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                            //将其理解为装饰器模式 在原有的普通扩展点上进行增强 在RPC服务发布与调用时可以提现</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                            instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> injectExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">((T) </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">wrapperClass</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getConstructor</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(type).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">newInstance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(instance)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>自适应扩展机制</h2>
<p>在上面普通扩展机制中其实已经提到了自适应扩展机制，在<code>ExtensionLoader</code>初始化构造函数时便会有<code>objectFactory</code>对象，此对象就是在IOC依赖注入时会使用到，它便是通过自适应扩展机制获取到的。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> type) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        this</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">type</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        objectFactory </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                (type </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> ExtensionFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> ?</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> :</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ExtensionFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getAdaptiveExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里获取到<code>ExtensionFactory</code>接口的所有扩展点实例，但是使用了<code>getAdaptiveExtension</code>方法，也就是说调用该方法便得到的是一个自适应扩展，并不是一个具体的扩展类。</p>
<p>虽然我们可以获取到具体的扩展点类，但是并不想一开始就获取，而是在运行时动态获取。如果一开始就调用<code>ExtensionLoader.getExtension()</code>获取了扩展点，那么之后便无法去改变它。</p>
<p>通过上述了解明白Dubbo通过一个URL去动态加载扩展点，同时url也是通过配置文件获取。这样我们就可以在配置文件中使用zookeeper作为注册中心，修改配置文件后又可以将redis作为配置中心。dubbo根据配置文件的URL进行驱动，自适应加载不同的注册中心，在源码中出现过很多次，与上面SPI获取指定扩展点相配合坐到灵活扩展、动态配置。</p>
<ul>
<li><code>@Adaptive</code>作用在类上，dubbo会将类作为自适应扩展类。</li>
<li><code>@Adaptive</code>作用在方法上，dubbo会动态的生成代码逻辑。例如<code>ProxyFactory</code>是一个自适应扩展类，注解作用在方法上时，将动态产生一个类叫做<code>ProxyFactory$Adaptive</code>，其中方法逻辑全部由dubbo生成。</li>
<li>一般自适应扩展指的是dubbo从URL获取到参数，用dubbo的@SPI方式使用参数拿到扩展点，从而达到自适应的效果。上面例子<code>ProxyFactory</code>自适应扩展类上也被@SPI注解作用。</li>
</ul>
<h4>getAdaptiveExtension</h4>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getAdaptiveExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">    -></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> createAdaptiveExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() #从缓存中获取 否则创建</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">        -></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getAdaptiveExtensionClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">newInstance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> #获取AdaptiveExtensionClass</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">            -></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getExtensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() # 加载当前扩展所有实现，看是否有实现被标注为</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#A626A4;--shiki-dark:#E5C07B">Adaptive</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">            -></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> createAdaptiveExtensionClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() #如果没有实现被标注为</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#A626A4;--shiki-dark:#E5C07B">Adaptive</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">，则动态创建一个Adaptive实现类</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">                -></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> createAdaptiveExtensionClassCode</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() #动态生成实现类java代码</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">                -></span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> compiler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">compile</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(code, classLoader)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> #动态编译java代码，加载类并实例化</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">        -></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> injectExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(instance)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>接下来就从<code>ExtensionLoader</code>的构造方法中找到<code>getAdaptiveExtension</code>方法，以该方法为入口看看自适应扩展点。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getAdaptiveExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //缓存获取</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Object</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> cachedAdaptiveInstance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (createAdaptiveInstanceError </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Failed to create adaptive instance: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                        createAdaptiveInstanceError</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">toString</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                        createAdaptiveInstanceError)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //double-check</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            synchronized</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (cachedAdaptiveInstance) {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> cachedAdaptiveInstance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    try</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                        //创建自适应扩展实例</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                        //这里需要关注createAdaptiveExtension方法</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                        instance </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> createAdaptiveExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                        cachedAdaptiveInstance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">set</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(instance);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">catch</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Throwable</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> t</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                        createAdaptiveInstanceError </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                        throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Failed to create adaptive instance: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">toString</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> t)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (T) instance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这个方法中和之前的逻辑差不多，缓存获取、double-check、创建扩展点实例。</p>
<p>在此我们需要着重关注<code>createAdaptiveExtension</code>方法</p>
<h4>createAdaptiveExtension</h4>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> createAdaptiveExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        try</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //getAdaptiveExtensionClass获取到自适应类后进行IOC注入，IOC注入和之前的逻辑一样</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> injectExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">((T) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getAdaptiveExtensionClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">newInstance</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">catch</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Exception</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> e</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Can't create adaptive extension "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> type </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ", cause: "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> e</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> e)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里逻辑比较简单，通过<code>getAdaptiveExtensionClass</code>方法获取到自适应类，然后再IOC注入，注入逻辑前面已经提到了。</p>
<p>那么接下里再看看<code>getAdaptiveExtensionClass</code>方法如何获取自适应类。</p>
<h4>getAdaptiveExtensionClass</h4>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getAdaptiveExtensionClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //加载所有扩展点</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        getExtensionClasses</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //如果扩展点上存在@Adaptive注解 则cachedAdaptiveClass缓存变量不为空</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (cachedAdaptiveClass </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //存在@Adaptive注解作用在类上 表示该自适应扩展类为人工编码 直接返回</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> cachedAdaptiveClass</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //表示没有@Adaptive注解标志 那么dubbo将生成自适应扩展类</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> cachedAdaptiveClass </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> createAdaptiveExtensionClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在<code>getAdaptiveExtensionClass</code>中开始会使用<code>getExtensionClass</code>加载所有自适应扩展类，然后判断是否存在<code>@Adaptive</code>注解</p>
<ul>
<li>如果类上存在<code>@Adaptive</code>注解，便会将其赋值给<code>cacheAdaptiveClass</code>对象，表示此自适应扩展类为人工编码，直接返回。</li>
<li>如果构造函数参数为扩展点接口类型，表示此时为装饰类。</li>
<li>普通类，为普通扩展类。</li>
</ul>
<p>下面看看这个类图。</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gsoe73lyzxj31nk0n8jun.jpg" alt="image-20210721110640532" loading="lazy"></p>
<p>这里面我们着重看一下<code>AdaptiveExtensionFactory</code>如何自适应创建扩展类。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#A626A4;--shiki-dark:#E5C07B">Adaptive</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> AdaptiveExtensionFactory</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> implements</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> ExtensionFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> final</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> List</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ExtensionFactory</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> factories</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> AdaptiveExtensionFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //自定义调整扩展点类的加载</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        ExtensionLoader</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ExtensionFactory</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">> </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">loader</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ExtensionFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        List</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ExtensionFactory</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">> </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">list</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> ArrayList</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ExtensionFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> name</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> :</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getSupportedExtensions</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //扩展点类加载得到后 直接放入factories中</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            list</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">add</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">loader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        factories </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> Collections</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">unmodifiableList</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(list);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#A626A4;--shiki-dark:#E5C07B">Override</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">> </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //由于factories已经获取到了ExtensionFactory的所有扩展点类 这里依次读取即可</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ExtensionFactory</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> factory</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> :</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> factories) {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">            T</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> extension</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> factory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(type, name);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //获取到type name 这样的扩展点 直接返回</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (extension </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> extension;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里可以看到<code>AdaptiveExtensionFactory</code>使用自定义的方式加载了<code>ExtensionFactory</code>的所有扩展点类，这样只需要在配置文件里面添加一个<code>ExtensionFactory</code>扩展点类，便可以动态的加载IOC容器，多增加一个IOC依赖来源。</p>
<p>同时在上面<code>AdaptiveExtensionFactory</code>类上面存在<code>@Adaptive</code>注解，那么便会直接将其返回，如果并不存在该注解dubbo便会自动创建自适应扩展类。这里继续回到上面<code>createAdaptiveExtension</code>方法的最后一行<code> createAdaptiveExtensionClass();</code></p>
<h4>createAdaptiveExtensionClass</h4>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> createAdaptiveExtensionClass</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //创建一个生成类 类型=DownloadStrategy 扩展点类型 ，扩展点接口的class对象 和 默认扩展点名称</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //这里需要看看generate方法是如何生成的</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> code </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> AdaptiveClassCodeGenerator</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> cachedDefaultName)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generate</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //拿到ExtensionLoader的ClassLoader</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        ClassLoader</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> classLoader </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> findClassLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //自适应方式拿到编译类 然后将代码进行编译 classLoader进行加载 最终编程一个Class对象</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        org</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">common</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">compiler</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Compiler</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> compiler </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">common</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">compiler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">Compiler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getAdaptiveExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> compiler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">compile</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(code, classLoader);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul>
<li>加载创建一个生成类，类型为扩展点接口类型，还有默认扩展点名称</li>
<li>拿到<code>ExtensionLoader</code>的<code>ClassLoader</code></li>
<li>自适应方式拿到编译类，然后将其编译并且通过<code>ClassLoader</code>加载，最终得到一个Class对象。</li>
</ul>
<h4>generate 生成自适应扩展点类</h4>
<p>上面提到了重点是这个<code>generate</code>方法用来生成自适应扩展点类。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generate</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // no need to generate adaptive class since there's no adaptive method found.g</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //方法上无法找到@Adaptive注解 不需要生成自适应类 因为找不到自适应方法</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">hasAdaptiveMethod</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"No adaptive method exist on extension "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ", refuse to create the adaptive class!"</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        StringBuilder</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> code </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> StringBuilder</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //生成包名 package cc.ccoder.loader;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generatePackageInfo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //导入依赖 import org.apache.dubbo.common.extension.ExtensionLoader;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generateImports</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //这里生成类名 之前说到的添加一个$Adaptive后缀 例如ProxyFactory生成的自适应代码ProxyFactory$Adaptive</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //public class %s$Adaptive implements %s {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generateClassDeclaration</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Method</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">[] methods </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getMethods</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Method</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> method </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> methods) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //依次生成方法</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generateMethod</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(method));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"}"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">logger</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isDebugEnabled</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            logger</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">debug</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">toString</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //返回代码 此时代码结构已经有了返回即可</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">toString</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>主要是这几个步骤：</p>
<ul>
<li>判断是否存在<code>@Adaptive</code>注解，是否需要生成自适应类</li>
<li>生成包名 <code>package xxxxxx</code></li>
<li>导入依赖<code>inport org.apache.dubbo.common.extension.ExtensionLoader</code></li>
<li>生成类名，并且这里的类名会有一个后缀<code>$Adaptive</code>。<code>public class %s$Adaptive implements %s {</code></li>
<li>然后逐个生成自适应扩展点的接口方法
<ul>
<li>这里就需要着重看一下<code>generateMethod</code>方法中是如何生成方法</li>
</ul>
</li>
<li>返回自适应扩展点类代码</li>
</ul>
<h4>generateMethod</h4>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generateMethod</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Method</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> method) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //获取方法的返回值类型</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> methodReturnType </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> method</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getReturnType</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getCanonicalName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //获取方法的名称</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> methodName </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> method</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //获取方法内容</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> methodContent </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generateMethodContent</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(method)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //获取方法的参数</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> methodArgs </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generateMethodArguments</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(method)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //获取方法抛出异常</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> methodThrows </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generateMethodThrows</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(method)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //通过这个模板生成方法</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //"public %s %s(%s) %s {\n%s}\n";</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">format</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(CODE_METHOD_DECLARATION, methodReturnType, methodName, methodArgs, methodThrows, methodContent);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>从这个<code>generateMethod</code>我们已经有些眉目了。获取待生成方法的返回值类型，获取方法名称，获取方法内容，获取方法参数以及抛出的异常信息，并且通过<code>public %s %s(%s) %s {\n%s}\n</code>这个模板进行生成。那么这里我们只需要着重看一下如何获取方法内容。通过<code>generateMethodContext</code>方法生成方法内容。</p>
<h5>generateMethodContext</h5>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generateMethodContent</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Method</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> method) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //首选获取到方法上的@Adaptive注解</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Adaptive</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> adaptiveAnnotation </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> method</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getAnnotation</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">Adaptive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        StringBuilder</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> code </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> StringBuilder</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">512</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (adaptiveAnnotation </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //如果此方法上面没有@Adaptive注解 便不为此方法生成动态方法 并且抛出一个异常UnsupportedOperationException</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generateUnsupported</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(method)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //获取URL参数索引</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            int</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> urlTypeIndex </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getUrlTypeIndex</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(method)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // found parameter in URL type</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //在URL类型中找到参数,如果不为-1表示找到</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (urlTypeIndex </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                // Null Point check</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //添加一个arg == null的校验</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generateUrlNullCheck</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(urlTypeIndex));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                // did not find parameter in URL type</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //没有找到 在其他方法中判断是否可以获取到URL getUrl这个方法</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generateUrlAssignmentIndirectly</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(method));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //获取注解上的value值 代表获取扩展点时get的name值 ，如果不存在则使用类名的值作为键</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">            String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">[] value </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getMethodAdaptiveValue</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(adaptiveAnnotation)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //判断参数中是否有Invocation类型的参数，org.apache.dubbo.rpc.Invocation</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            boolean</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> hasInvocation </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> hasInvocationArgument</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(method)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            </span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //生成Invocation参数值的代码 并且进行null校验</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generateInvocationArgumentNullCheck</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(method));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            </span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //生成从url获取参数的代码 getMethodParameter getParameter getProtocol</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generateExtNameAssignment</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(value, hasInvocation));</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // check extName == null?</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //校验extName==null 的代码</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generateExtNameNullCheck</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(value));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            </span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //生成getExtensionLoader(xxx.class).getExtension(extName)的代码</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generateExtensionAssignment</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // return statement</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // 生成return语句 扩展点类执行方法</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">generateReturnAndInvocation</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(method));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">toString</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>上述代码表示生成扩展点类方法内容的方法</p>
<ul>
<li>
<p>首先判断方法上是否存在<code>@Adaptive</code>注解，若没有不为此方法生成动态方法，并且抛出以下异常信息，表示该方法不支持动态。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> UnsupportedOperationException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"The method %s of interface %s is not adaptive method!"</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div></li>
<li>
<p>生成<code>getUrl</code>方法,动态获取到配置的参数 此时已经校验了参数中是否存在URL</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (arg</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">%</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">d </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalArgumentException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"url == null"</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">%</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">s url </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> arg</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">%</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">d</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>如果没有便会在其他方法中是否可以获得到url.通过<code>generateUrlAssignmentIndirectly</code>方法判断。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">   private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generateUrlAssignmentIndirectly</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Method</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> method) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //获取参数类型</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Class</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">[] pts </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> method</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getParameterTypes</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        //遍历所有方法中的参数</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Map</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Integer</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> getterReturnUrl </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> HashMap</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // find URL getter method</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> i </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> i </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> pts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">length</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ++</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">i) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            for</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Method</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> m </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> pts[i]</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getMethods</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">                String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> name </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> m</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //是否已get开头或者参数方法名长度大于3</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //方法名是public的 isPublic</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //方法不是static的 isStatic</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //方法没有参数 getParameterTypes.length == 0</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                //方法返回值为URL类型 org.apache.dubbo.common.URL</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> ((</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">startsWith</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"get"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">length</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">                        &#x26;&#x26;</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> Modifier</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isPublic</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">m</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getModifiers</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">())</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">                        &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> !</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">Modifier</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">isStatic</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">m</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getModifiers</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">())</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">                        &#x26;&#x26;</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> m</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getParameterTypes</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">length</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">                        &#x26;&#x26;</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> m</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getReturnType</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> ==</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> URL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    getterReturnUrl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">put</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(name, i);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">getterReturnUrl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> &#x3C;=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // getter method not found, throw</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Failed to create adaptive class for interface "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">                    +</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ": not found url parameter or url attribute in parameters of method "</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> method</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        Integer</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> index </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> getterReturnUrl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"getUrl"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> (index </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            //生成获取URL的代码</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generateGetUrlNullCheck</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(index</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> pts[index]</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "getUrl"</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">            Map</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Entry</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Integer</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> entry </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> getterReturnUrl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">entrySet</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">iterator</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">next</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generateGetUrlNullCheck</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">entry</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getValue</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(),</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> pts[</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">entry</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getValue</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">]</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> entry</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>那么接下来重点便是这个<code>generateGetUrlNullCheck</code>方法</p>
</li>
</ul>
<h5>generateGetUrlNullCheck</h5>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    /**</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * 1, test if argi is null</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * 2, test if argi.getXX() returns null</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * 3, assign url with argi.getXX()</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     */</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> generateGetUrlNullCheck</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> index</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Class</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">></span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> method) {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // Null point check</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        StringBuilder</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> code </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> StringBuilder</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">format</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"if (arg%d == null) throw new IllegalArgumentException(</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\"</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">%s argument == null</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\"</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">);</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                index, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()));</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">format</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"if (arg%d.%s() == null) throw new IllegalArgumentException(</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\"</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">%s argument %s() == null</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\"</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">);</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                index, method, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), method));</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">append</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">format</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"%s url = arg%d.%s();</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">URL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), index, method));</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> code</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">toString</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>从上面注释可以看出</p>
<ul>
<li>判断参数费否为空，并且抛出异常</li>
<li>判断参数getXx是否为空 并且抛出异常</li>
<li>将参数值赋值给<code>org.apache.dubbo.common.URL</code>这个类型。</li>
</ul>
<p>也就是说我们最终是从URL获取参数</p>
<ul>
<li>
<p>查看是否存在<code>involocation</code>类型，如有则从url中获取<code>involocation.getMethonName</code>参数</p>
</li>
<li>
<p>没有则从<code>@Apaptive</code>注解获取value值，当存在多个value时,则从value1、value2依次往后取。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">//@Adaptive注解value</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">[] </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">value</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">() </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">default</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> {}</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div></li>
<li>
<p>如果多个value均没有取到后则从<code>@SPI</code>注解中取。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">dubbo</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">//10.20.54.65:20886/cc.ccoder.exchange.service.facade.api.ExchangeFacade?</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div></li>
</ul>
<h4>ProxyFactory$Adaptive</h4>
<p>前面提到了<code>ProxyFactory</code>会自适应生成扩展点类，下面便是生成的扩展点类。</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#383A42;--shiki-dark:#C678DD"> org.apache.dubbo.rpc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> org.apache.dubbo.common.extension.ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> ProxyFactory$Adaptive</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> implements</span><span style="--shiki-light:#C18401;--shiki-dark:#E06C75"> org.apache.dubbo.rpc.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ProxyFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> java</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">lang</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getProxy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Invoker</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> arg0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> throws</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> org.apache.dubbo.rpc.RpcException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (arg0 </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalArgumentException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"org.apache.dubbo.rpc.Invoker argument == null"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">arg0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getUrl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalArgumentException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"org.apache.dubbo.rpc.Invoker argument getUrl() == null"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        org</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">common</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">URL</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> url</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> arg0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getUrl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> extName</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> url</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getParameter</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"proxy"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"javassist"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (extName </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url ("</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> url</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">toString</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ") use keys([proxy])"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        org</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ProxyFactory</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> extension</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ProxyFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(extName);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> extension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getProxy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(arg0);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> java</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">lang</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getProxy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Invoker</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> arg0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">boolean</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> arg1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> throws</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> org.apache.dubbo.rpc.RpcException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (arg0 </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalArgumentException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"org.apache.dubbo.rpc.Invoker argument == null"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">arg0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getUrl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalArgumentException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"org.apache.dubbo.rpc.Invoker argument getUrl() == null"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        org</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">common</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">URL</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> url</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> arg0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getUrl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> extName</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> url</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getParameter</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"proxy"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"javassist"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (extName </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url ("</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> url</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">toString</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ") use keys([proxy])"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        org</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ProxyFactory</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> extension</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ProxyFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ProxyFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(extName);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> extension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getProxy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(arg0, arg1);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> org</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Invoker</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getInvoker</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">java</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">lang</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> arg0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">java</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">lang</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Class</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> arg1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">common</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">URL</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> arg2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> throws</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> org.apache.dubbo.rpc.RpcException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (arg2 </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalArgumentException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"url == null"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        org</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">common</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">URL</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> url</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> arg2;</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> extName</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> url</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getParameter</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"proxy"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"javassist"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (extName </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> null</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IllegalStateException</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url ("</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> url</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">toString</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ") use keys([proxy])"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">        org</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#E45649;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ProxyFactory</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> extension</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ProxyFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtensionLoader</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">apache</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">dubbo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">rpc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">ProxyFactory</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getExtension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(extName);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> extension</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getInvoker</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(arg0, arg1, arg2);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>总结一下</h2>
<ul>
<li><code>ExtensionLoader</code>加载一个具体的扩展点实现类。</li>
<li>每个扩展点只会对应一个<code>ExtensionLoader</code>实例</li>
<li>每个扩展点实现只会有一个实例，但是一个扩展点实现可以有多个名称。</li>
<li>如果需要等到运行时才决定使用哪一个扩展点实现类，使用自适应扩展点实现便可.<code>AdaptiveExtensionFactory</code></li>
<li>判断<code>@Adaptive</code>注解是作用在<code>@SPI</code>注解的类上</li>
<li>如果扩展点存在多个Wrapper,那么最终执行顺序是不固定的，内部使用<code>ConcurrentHashSet</code>存储</li>
</ul>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="Dubbo"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-12-02T14:58:56.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">ISO20022标准介绍</title>
    <id>https://blog.ccoder.cc/posts/2021/ISO20022-biao-zhun-jie-shao.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/ISO20022-biao-zhun-jie-shao.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>[TOC]</p>
<h2>1.什么是ISO20022 标准</h2>
<blockquote>
<p>​    ISO 20022 是一种新兴的<strong>全球开放式支付消息传递标准</strong>。一种为全球支付数据创建的通用语言和模型，一种提供笔其他标准更高质量的数据，这意味着所有人都能够获得更高质量的付款。一种可以适应新需求和新方法的产品。一个不受单一利益控制的标准。一种可供业内任何人使用并在任何网络上实施的工具。</p>
</blockquote>
<p>我们将从ISO20022是什么以及为何可以在各平台机构中流行起来，它的诞生是传递了怎样的一种价值观，或者说解决了哪些行业问题。</p>]]></summary>
    <content type="html"><![CDATA[<p>[TOC]</p>
<h2>1.什么是ISO20022 标准</h2>
<blockquote>
<p>​    ISO 20022 是一种新兴的<strong>全球开放式支付消息传递标准</strong>。一种为全球支付数据创建的通用语言和模型，一种提供笔其他标准更高质量的数据，这意味着所有人都能够获得更高质量的付款。一种可以适应新需求和新方法的产品。一个不受单一利益控制的标准。一种可供业内任何人使用并在任何网络上实施的工具。</p>
</blockquote>
<p>我们将从ISO20022是什么以及为何可以在各平台机构中流行起来，它的诞生是传递了怎样的一种价值观，或者说解决了哪些行业问题。</p>
<p>然后再看看这个标准如何成功传递信息，有哪些机构平台参与了该标准的制作，到目前为止该标准涵盖的行业范围。</p>
<p>同时，随着行业发展，有新的内容产生时，如何将这些新兴内容添加到该标准中，这就是该标准的注册流程。后面会提到该标准最终实时落地方案是一个标准xml, ANS存储库。</p>
<p>在这里我们可以看到通用、信息标准传递。如果我们可以在所有支付通信中使用单一的消息标准，那么我们就可以节约很多兼容标准不一样所浪费的时间和精力。</p>
<ul>
<li>
<p>无论交易对手方是谁？金融机构、金融信息机构商、对私、对公客户都可以使用同一套标准，</p>
</li>
<li>
<p>无论是哪个业务领域？(支付行业、证券行业、贸易服务、发卡行、外汇等)都是可以的，</p>
</li>
<li>
<p>无论是哪个网络？(公网、私网、国内或者国际)都如此。</p>
</li>
</ul>
<h2>2.价值体系</h2>
<h3>2.1 解决痛点</h3>
<p>接下来是ISO 20022 的价值体系和解决痛点问题。</p>
<p>ISO20022旨在实现金融机构及其市场基础设施和最终用户社区之间通信互操性。</p>
<p>并且解决许多对于XML金融消息标准重叠化问题。指定所有金融财务标准都是用单一标准化方法，这套标准包括使用方法、指定流程、标准词典存储库等。</p>
<p>从这里我们可以看到从本世纪初所流行通信方法。并且都是使用XML方式。</p>
<p>有一个问题是：XML并不是一种语言，而是一种元语言。也就是说通过XML标准格式每个人可以定义自己的“方言”。那么这就导致出现了很多种“方言”，并且当多个“方言”专注于同一个领域时，势必会造成资源浪费，重复定义，并且也会进一步增加分歧风险。</p>
<blockquote>
<ul>
<li>MDDL: Market Data Definition Language 市场数据定义语言，是一种基于XML的消息格式，用于交换与金融工具、市场数据相关信息，由SIIA(Software &amp; Information Industry Association 软件信息产业协会 ) 和 FISD(Financial information services division 金融信息服务部) 开发，2000年得到使用，并且获得全行业认可。</li>
<li>FIX: Financial information eXchange 金融信息交换协议 1992年发起的电子通信协议，用于与证券交易、市场相关的国际实时信息交换。</li>
<li>VRXML: Vendor Reporting Extensible Markup Language 供应商报表协议 是一种基于XML 涉及市场数据计费、报表、库存管理等。最初由纽交所开发，目的是使所有部分能够以通用XML格式生成、传输、接收和处理发票和报表。</li>
</ul>
</blockquote>
<p>上述数层间金融行业事业的一些标准协议。</p>
<h3>2.2 ISO20022 解决方案</h3>
<p>为了解决上述的行业“方言”痛点问题，在此ISO给出了建议的解决方案：</p>
<p>所有金融标准计划都使用单一标准方法。</p>
<p>为了解决这个问题，ISO提出：</p>
<ul>
<li>一个通用的开发方法</li>
<li>一个通用的流程</li>
<li>一个通用的存储库供所有金融标准计划使用。</li>
</ul>
<p>这便是ISO 20022.</p>
<p>如果所有的金融财务标准都是用该套配方，我们将避免重复工作、并且所有的开发通信消息就减少了沟通分歧产生，看起来就像是同一个开发人员开发一样。</p>
<h3>2.3 长期趋同 短期共存</h3>
<ul>
<li>趋于同一个标准是一个长期目标</li>
<li>多项标准共存，快速适应市场竞争压力和响应监管要求</li>
<li>多标准如何“短期”共存</li>
</ul>
<p>最终金融行业趋于同一个标准是一个长期目标</p>
<p>但是在此期间，和现有标准需要共存，以快速适应市场竞争压力和响应监管要求。</p>
<p>ISO20022 不仅提供了一种趋于同一标准的长期目标的方法，同时还提供了一种促进多种标准“短期”共存的方法。</p>
<p>目前已经存在了很多标准，并且当标准彼此独立开发时，从一种标准到另外一种标准的转换需要将数据直接从一个应用映射到另外一个程序，这是一种高成本、不可扩展、难以维护和试试的方案。</p>
<h3>2.4 降低复杂度</h3>
<p>每当我们需要支持新的标准时，都会城北的增加复杂性和成本的。</p>
<p></p>
<p>在此我举个栗子：</p>
<p>我们有7个标准，每个标准需要与其他6个标准中的每一个来回通信。我们就需要7*6=42个接口来翻译报文。</p>
<p>但是，如果我们增加标准的数量，比如增加3个标准，我们总共有10个标准，每个标准都需要与其他9个标准进行通信。</p>
<p>那么此时我们需要10*9=90个翻译接口。</p>
<p>对于我们7个标准中的每一个都使用了单个消息模型，只需要将其转化一次到消息模型中，然后从另外的消息模型中进行接收。</p>
<p>换句话说，我们只需要为每个标准开发两个翻译接口就行了 （适配器模式）</p>
<h3>2.5 流程整合</h3>
<ul>
<li>标准通信流程整合</li>
<li>降低偶尔、更快的弹性变化</li>
<li>共享消息服务——单个共享解析器、消息独立规则引擎</li>
<li>统一监控、监管追踪</li>
</ul>
<p></p>
<p>从上面我们可以得知，标准实施可以降低成本，实现适应更快的弹性变化，以便提高整体的性能。</p>
<p>这种开发独立于语法的业务模型的方法是ISO20022标准的核心。</p>
<p>从长远来看，从模型生成的物理ISO20022消息将成为我们正在寻找的唯一标准，</p>
<p>在此之前，多种消息标准模型短期共存，长期趋同。</p>
<h2>3.ISO20022介绍</h2>
<p>这种图说明业务建模概念</p>
<p></p>
<p>每个机构都有自己一套内部数据对象来表达各种业务概念。ISO20022的目标是识别和标准化机构之间共享的概念，并将其存储在ISO 20022存储库的数字词典中。</p>
<p>在这里使用彼此之间商定的标准，就像乐高积木一样，开发人员可以构建与ISO20022语法无关的消息模型，然后根据所需的语法将其转换成目标消息格式。</p>
<p>当前首选的 ISO 20022 语法是 XML 和 ASN.1，但如果选择新的更好的语法，则不需要更改模型：只有将消息模型转换为所需消息格式的规则才会更改。此外，如果针对特定业务领域或特定细分市场使用另一种语法更有效，则使用 ISO 20022 消息模型可确保业务信息从一个消息顺利流向另一个消息，无论使用哪种语法传输该消息商业信息。</p>
<p>独立于语法的业务建模是 ISO 20022 标准的关键……</p>
<p>模型随着业务的发展而发展，而格式随着技术的发展而发展，以从自动化、易于实施、产品的开放性和廉价性等方面的最新创新中受益。 ISO 20022 配方提供了一种更好、更便宜和更快的方式开发和实施可互操作的消息标准。</p>
<h3>3.1 设计理念</h3>
<ul>
<li>基于建模的标准开发
<ul>
<li>独立于语法的业务标准</li>
<li>经过行业验证</li>
</ul>
</li>
<li>XML和ASN.1 的特定语法的设计规则
<ul>
<li>可预测和自动化</li>
<li>保护标准免受技术发展的影响</li>
</ul>
</li>
<li>逆向工程方法
<ul>
<li>保护行业投资并简化互操作性</li>
<li>为未来的迁移做准备</li>
</ul>
</li>
</ul>
<p>现在我们看到的是ISO20022的主要内容。详细说一下各项是代表含义：</p>
<p>​    独立于语法的业务建模方法是该标准最具创新性的特征。</p>
<p>​    这种建模方法允许开发人员在未来消息的物理格式之前并独立于其捕获“业务标准”。建模方法提出了一种两步法。</p>
<p>首先，开发者会描述整体的“业务模型”：谁是参与者，他们完成什么样的流程，他们需要什么样的信息来完成这些流程等。</p>
<p>一旦完成，他们将定义最佳的交易流程在正确的时间向正确的参与者传达所需的信息。</p>
<p>在接受之前，候选的 ISO 20022 模型由 ISO 提名的行业未来用户代表进行验证。这是为了在 ISO 20022 存储库中发布消息之前获得未来用户的支持。</p>
<p>ISO 20022 的另一个主要组成部分是它的一组预先商定的设计规则，用于将消息模型转换为所需语法的物理消息格式——目前是 XML 或 ASN.1。这些设计规则确保所有 ISO 20022 XML 或 ASN.1 模式的结构一致，以一种对接收者（和应用程序供应商）“可预测”的方式进行，从而更容易实现自动化。</p>
<p>语法设计规则与建模方法明确分离的事实确保了当/如果找到新的更好的语法解决方案时不需要更改模型。</p>
<p>此外，该标准的一部分是“逆向工程”技术，用于“重新捕获”现有不符合 ISO 20022 的消息标准的功能，并将其提供给 ISO 20022 模型，从而促进现有消息的互操作性、共存和迁移。他们符合 ISO 20022 的等效标准。</p>
<p>正是业务建模和逆向工程的结合使得 ISO 20022 在支持互操作性方面如此独特。</p>
<h3>3.2 注册流程</h3>
<ul>
<li>开发注册流程
<ul>
<li>明确识别活动和角色</li>
<li>业务专家和未来用户提前参与</li>
<li>技术参与</li>
</ul>
</li>
<li>ISO20022 标准存储库
<ul>
<li>业务流程目录和存储库</li>
<li>官方标准之外由注册机构维护</li>
</ul>
</li>
</ul>
<p>上面提到的是ISO20022的价值，在此再说说ISO20022 的另外两个部分，注册过程和仓储库。</p>
<ul>
<li>ISO20022描述了一个严格的注册过程，以避免重复工作并且确保开发的准确性。业务专家和未来潜在用户提前参与进来，以确保满足所有业务需求。</li>
</ul>
<p>社区的这种参与可能需要时间，但对于获得良好的标准、将要使用的标准来说绝对是至关重要的。</p>
<ul>
<li>ISO 20022 框架的基石是其财务存储库，其中存储了批准的模型、交易、消息及其组件。</li>
</ul>
<p>数据字段包含了模型和消息格式。消息格式包含了所有使用的组件，以及包含业务模型、事务和消息的业务流程目录。</p>
<p></p>
<p>一旦业务理由获得 RMG 批准，并且只要消息尚未获得 SEG 批准，这些消息就称为“候选 ISO 20022 消息”。 一旦获得 SEG 批准发布，这些消息就称为“ISO 20022 消息”或“符合 ISO 20022 的消息”。</p>
<ul>
<li>
<p><strong>RMG 注册管理组</strong></p>
<ul>
<li>批准新消息标准的商业理由</li>
<li>批准新成员实体</li>
<li>创建标准评估组 (SEG) 和 SubSEG</li>
</ul>
</li>
<li>
<p><strong>标准评估组、SEG 和 SubSEG</strong></p>
<ul>
<li>代表特定金融领域的未来用户</li>
<li>验证新的候选消息和变更请求</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>注册管理组</strong> <strong>(RMG- Registration Management Group)</strong> <strong>是最高注册机构</strong>。它由资深的行业专家组成，他们共同代表了金融行业的各个领域。 RMG 的作用是促进和支持金融服务参与者的参与，以促进高质量的全球相关 ISO 20022 合规商业模式的注册和维护，以交换金融服务的信息。其使命是确保 ISO 20022 是一个值得信赖的标准，为金融服务信息交换提供高质量的商业模式。</p>
<p>RMG 监督整个注册过程，包括其他注册机构的表现。如果无法达成共识，或者参与过程的各方之间存在冲突，则它充当“上诉法院”。</p>
<p>RMG 评估并优先考虑由希望开发新 ISO 20022 消息的提交组织引入的业务理由。它批准了希望参与 RMG、SEG/SubSEG 和 TSG 的新成员实体的申请。</p>
<p>RMG 还发起创建新的标准评估组 (SEG) 和 SubSEG。</p>
<p>包括 SUBSEG 在内的标准评估组 (SEG) 是行业专家组，每个专家组代表特定金融领域中 ISO 20022 消息的（未来）用户。他们的作用是确保候选 ISO 20022 消息真正满足未来用户的需求。所有候选 ISO 20022 消息都由一个或多个 SEG 验证，具体取决于消息的范围。 SEG 还批准对现有消息的更改。</p>
<p>注册机构 (RA) 是 ISO 20022 财务知识库的守护者。 SWIFT 已被 ISO 提名提供 RA 服务。 RA 的作用是指导提交组织，确保开发的模型符合 ISO 20022 技术规范，并将消息模型转换为兼容的 XML 或 ASN.1 模式。 RA 还负责维护 <a href="www.iso20022.org">ISO 20022 网站</a> 并定期发布 ISO 20022 存储库的更新摘录。</p>
<p>最后，技术支持组 (TSG) 是一组技术专家，可以帮助任何其他注册机构和提交组织解决与 ISO 20022 配方的使用相关的技术问题。</p>
</blockquote>
<h3>3.3 参与机构</h3>
<p>RMG 包括大量成员实体（国家和组织），表明了社区对 ISO 20022 的兴趣。</p>
<ul>
<li><strong>参与国家</strong>
<ul>
<li>AT, AU, BR, CA, CH, CN, DE, DK, FI, FR, GB, IN, IT, JP, KR, NL, NO, SE, SG, US, ZA.</li>
</ul>
</li>
<li><strong>参与机构组织</strong>
<ul>
<li>ACTUS, Bank of England, CFTC, Clear stream, DTCC, ECB, EPC, Euroclear, FPL, ISDA/FpML, ISITC, MasterCard, NACHA/IFX, nexo, OMG, SWIFT, Ripple Net, VISA</li>
</ul>
</li>
<li><strong>会议频次</strong>
<ul>
<li>一年两次</li>
</ul>
</li>
<li><strong>重大决策</strong>
<ul>
<li>创建六个标准评估组(SEG):
<ul>
<li>2005 年的支付和证券</li>
<li>2006 年的贸易服务和外汇</li>
<li>2008 年的卡和相关零售金融服务</li>
<li>2016 年的衍生产品 Sub SEG</li>
</ul>
</li>
<li>ISO 20022 报文开发项目的批准</li>
<li>批准新的 ISO 20022 成员实体</li>
</ul>
</li>
</ul>
<h2>4 .参考链接</h2>
<ul>
<li>
<p><a href="https://www.iso20022.org/about-iso-20022" target="_blank" rel="noopener noreferrer">About ISO 20022</a></p>
</li>
<li>
<p><a href="https://www.swift.com/standards/iso-20022" target="_blank" rel="noopener noreferrer">SWIFT-What is ISO 20022</a></p>
</li>
<li>
<p><a href="https://www.iso20022.org/iso-20022-message-definitions" target="_blank" rel="noopener noreferrer">Catalogue of Message</a></p>
</li>
<li>
<p><a href="https://www.iso20022.org/iso-20022-message-definitions" target="_blank" rel="noopener noreferrer">ISO 20022 message definitions</a></p>
</li>
<li>
<p><a href="https://en.wikipedia.org/wiki/Financial_Information_eXchange" target="_blank" rel="noopener noreferrer">FIX-Financial Information eXchange</a></p>
</li>
<li>
<p><a href="https://en.wikipedia.org/wiki/MDDL" target="_blank" rel="noopener noreferrer">MDDL-Market Data Definition Language</a></p>
</li>
<li>
<p><a href="https://www.nyse.com/market-data/vrxml" target="_blank" rel="noopener noreferrer">VRXML-Vendor Reporting Extensible Markup Language</a></p>
</li>
<li>
<p><a href="http://std.samr.gov.cn/gb/search/gbDetailed?id=5DDA8B9DB2EE18DEE05397BE0A0A95A7" target="_blank" rel="noopener noreferrer">金融服务 金融业通用报文方案 第5部分：反向工程</a></p>
</li>
<li>
<p><a href="http://iso20022.tech/article/iso200224dummies1" target="_blank" rel="noopener noreferrer">什么是ISO 20022</a></p>
</li>
<li>
<p><a href="http://std.samr.gov.cn/gb/search/gbDetailed?id=5DDA8B9D9F1B18DEE05397BE0A0A95A7" target="_blank" rel="noopener noreferrer">金融服务 金融业通用报文方案 第2部分：UML概况</a></p>
</li>
<li>
<p><a href="http://std.samr.gov.cn/gb/search/gbDetailed?id=5DDA8B9DA93418DEE05397BE0A0A95A7" target="_blank" rel="noopener noreferrer">金融服务 金融业通用报文方案 第3部分：建模导则</a></p>
</li>
<li>
<p><a href="https://www.cfstc.org/jinbiaowei/2929546/2929550/2968504/index.html" target="_blank" rel="noopener noreferrer">ISO 20022标准在中国金融业的应用</a></p>
</li>
<li>
<p><a href="https://www.cufir.org.cn/cufir/index.html" target="_blank" rel="noopener noreferrer">中国金融业通用报文库</a></p>
</li>
</ul>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="课题研究"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-11-30T00:00:00.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">ISO20022消息建模</title>
    <id>https://blog.ccoder.cc/posts/2021/ISO20022-xiao-xi-jian-mo.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/ISO20022-xiao-xi-jian-mo.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>[TOC]</p>
<h2>1.消息模型</h2>
<p>在ISO上下文中，该标准描述了赖以表达信息的协议，而语法是用表达信息的格式或者语言。消息定义提供了对可在各方之间交换的信息和数据格式，包括字段长度、代码、字符集等分类。</p>
<p>ISO 20022消息可用于完整的端到端支付，包括客户—银行(支付)、银行—银行(支付清算与结算)等，这些金融消息定义分为多个业务领域。同时是由4个业务领域代码来标志。</p>
<ul>
<li>acmt—Account Management 账户管理</li>
<li>camt—Cash Management 现金管理</li>
<li>pain—Payments Initiation 支付发起</li>
<li>pacs—Payments Clearing and Settlement 支付清算与结算</li>
<li>reda—Reference Data 参考数据</li>
<li>remt—Payments Remittance Advice 付款汇款建议</li>
<li>等等标准可以查看<a href="https://www.iso20022.org/sites/default/files/documents/D7/ISO20022_BusinessAreas.pdf" target="_blank" rel="noopener noreferrer">ISO 20022 Business Areas</a></li>
</ul>]]></summary>
    <content type="html"><![CDATA[<p>[TOC]</p>
<h2>1.消息模型</h2>
<p>在ISO上下文中，该标准描述了赖以表达信息的协议，而语法是用表达信息的格式或者语言。消息定义提供了对可在各方之间交换的信息和数据格式，包括字段长度、代码、字符集等分类。</p>
<p>ISO 20022消息可用于完整的端到端支付，包括客户—银行(支付)、银行—银行(支付清算与结算)等，这些金融消息定义分为多个业务领域。同时是由4个业务领域代码来标志。</p>
<ul>
<li>acmt—Account Management 账户管理</li>
<li>camt—Cash Management 现金管理</li>
<li>pain—Payments Initiation 支付发起</li>
<li>pacs—Payments Clearing and Settlement 支付清算与结算</li>
<li>reda—Reference Data 参考数据</li>
<li>remt—Payments Remittance Advice 付款汇款建议</li>
<li>等等标准可以查看<a href="https://www.iso20022.org/sites/default/files/documents/D7/ISO20022_BusinessAreas.pdf" target="_blank" rel="noopener noreferrer">ISO 20022 Business Areas</a></li>
</ul>
<h2>2.支付发起—pain(Payments Initiation)</h2>
<p></p>
<h2>3.支付清算与结算—pacs(Payments Clearing and Settlement)</h2>
<p></p>
<h2>4.现金管理—camt(Cash Management)-(Notification To Receive)</h2>
<p></p>
<h2>5.参考连接</h2>
<ul>
<li><a href="https://www.finanssiala.fi/wp-content/uploads/2021/03/ISO20022_Payment_Guide.pdf" target="_blank" rel="noopener noreferrer">ISO 20022 Payment Guide</a></li>
<li><a href="https://www.iso20022.org/sites/default/files/documents/D7/ISO20022_BusinessAreas.pdf" target="_blank" rel="noopener noreferrer">ISO 20022 Business Areas</a></li>
</ul>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="课题研究"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-12-01T00:00:00.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">ISO20022应用场景</title>
    <id>https://blog.ccoder.cc/posts/2021/ISO20022-yin-yong-chang-jin.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/ISO20022-yin-yong-chang-jin.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>[TOC]</p>
<h2>ISO20022标准应用前景展望</h2>
<p>​        ISO 20022《金融服务　金融业通用报文方案》标准是针对金融行业信息交换问题，利用网络及XML技术制订的一个先进的通用报文方案。目前，符合ISO 20022标准的报文规范已在全球范围内得到广泛的应用。ISO对标准的推广使用非常重视，专门组建了ISO 20022标准报文库供全球金融界免费使用，并成立了ISO 20022注册管理机构（RMG）、标准评估机构（SEG）、注册机构（RA）负责该库的维护管理。目前，依据ISO 20022《金融服务　金融业通用报文方案》标准，国际上已开发了4类报文标准，它们是支付（Payment）、外汇与衍生品（FX）、证券（Securities）、贸易服务（Trade Services），共计265项，这些成熟的报文标准均经过ISO 20022注册管理机构的审核批
准，纳入了ISO 20022库中，成为全球通用的金融业务报文标准。</p>]]></summary>
    <content type="html"><![CDATA[<p>[TOC]</p>
<h2>ISO20022标准应用前景展望</h2>
<p>​        ISO 20022《金融服务　金融业通用报文方案》标准是针对金融行业信息交换问题，利用网络及XML技术制订的一个先进的通用报文方案。目前，符合ISO 20022标准的报文规范已在全球范围内得到广泛的应用。ISO对标准的推广使用非常重视，专门组建了ISO 20022标准报文库供全球金融界免费使用，并成立了ISO 20022注册管理机构（RMG）、标准评估机构（SEG）、注册机构（RA）负责该库的维护管理。目前，依据ISO 20022《金融服务　金融业通用报文方案》标准，国际上已开发了4类报文标准，它们是支付（Payment）、外汇与衍生品（FX）、证券（Securities）、贸易服务（Trade Services），共计265项，这些成熟的报文标准均经过ISO 20022注册管理机构的审核批
准，纳入了ISO 20022库中，成为全球通用的金融业务报文标准。</p>
<p>​    在我国，ISO 20022标准化开发方法也逐步应用到部分重要金融业信息系统的开发过程。</p>
<ul>
<li>中央银行会计核算数据集中系统（ACS）</li>
<li>中国人民银行第二代支付系统</li>
<li>中国人民银行网上支付跨行清算系统（EBPS</li>
<li>中国人民银行电子商业汇票系统（ECDS）</li>
<li>人民币跨境收付信息管理系统（RCPMIS）等。</li>
</ul>
<p>下一步，中国人民银行将以ISO 20022标准的实践应用为契机，逐步建立“中国人民银行系统互联报文库”，建设中国人民银行信息化基础设施，推动信息系统互联互通标准化。</p>
<p>​        ISO 20022标准化开发方法在国内金融业的逐步实施，将为我国金融业信息系统通用报文的开发带来新的理念和活力，为未来信息系统间信息交互与标准统一奠定良好基础。</p>
<h2>应用案例</h2>
<h3><a href="https://www.eigpay.com/productPage/ISO20022.html?id=product" target="_blank" rel="noopener noreferrer">仁聚汇通—ISO20022转化器</a></h3>
<ul>
<li>支持ISO 20022、SWIFT、ISO 8583等各种金融报文格式转换，并可灵活定制的适配器产品。</li>
<li>完全兼容ISO20022、ISO8583、SWIFT、国内外第三方支付平台等报文标准 可应用于支付、证券、外汇、资本市场等不同行业</li>
</ul>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="课题研究"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-12-03T18:28:16.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">XTransfer-(高级)支付后端开发工程师-面试总结</title>
    <id>https://blog.ccoder.cc/posts/2021/XTransfer-one.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/XTransfer-one.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<h2><strong>简单说下SFTP和FTP区别</strong></h2>
<p>由于目前是做的支付行业项目，涉及到银行出入款项目可能会文件服务器，所以算是一个简单的开场问题。</p>
<p>ftp和sftp都是日常工作中常用的文件传输方式。</p>
<h3>FTP</h3>
<ul>
<li>
<p>需要使用客户端和服务端进行交互。服务端用来存储文件，客户端可以使用FTP协议访问服务端上的资源。</p>
</li>
<li>
<p>默认开放21、20两个端口。21端口用于传输控制类消息，20端口是否使用取决于传输模式：被动模式(Passive)和主动模式(Port)。当然如果使用被动模式，具体使用哪个端口需要客户端和服务端双方协商。</p>
</li>
<li>
<p><strong>主动模式</strong></p>
<p></p>
<p>FTP客户端和服务器首先通过Port 21端口进行建立连接，通过这个通道发送命令。客户端需要接受数据时在此端口上进行Port命令。Port命令包含了客户端用什么端口进行接受数据，在传输数据时服务器端通过自己的TCP21端口连接到客户端指定的端口进行发送数据。</p>
</li>
<li>
<p><strong>被动模式</strong></p>
<p></p>
<p>建立通道与主动模式相似，建立之后是Pasv命令。服务器收到呢Pasv命令后随机打开一个高端端口(大于1024)并且通知客户端在这个端口上进行请求，客户端连接FTP服务器此端口，通过三次握手进行建立通道，然后服务器通过这个端口进行数据的传输。</p>
</li>
<li>
<p>注意有防火墙的限制，很多防火墙限制了从外部访问发起的连接，所以防火墙和内网中的FTP很多都是不支持Pasv模式的，因此客户端无法通过防火墙来打开一个高端端口。然后很多内网的客户端无法使用Port模式进行登录FTP服务器，因为从服务器的TCP 20端口无法和内网的客户端建立一个新的连接。</p>
</li>
</ul>]]></summary>
    <content type="html"><![CDATA[<h2><strong>简单说下SFTP和FTP区别</strong></h2>
<p>由于目前是做的支付行业项目，涉及到银行出入款项目可能会文件服务器，所以算是一个简单的开场问题。</p>
<p>ftp和sftp都是日常工作中常用的文件传输方式。</p>
<h3>FTP</h3>
<ul>
<li>
<p>需要使用客户端和服务端进行交互。服务端用来存储文件，客户端可以使用FTP协议访问服务端上的资源。</p>
</li>
<li>
<p>默认开放21、20两个端口。21端口用于传输控制类消息，20端口是否使用取决于传输模式：被动模式(Passive)和主动模式(Port)。当然如果使用被动模式，具体使用哪个端口需要客户端和服务端双方协商。</p>
</li>
<li>
<p><strong>主动模式</strong></p>
<p></p>
<p>FTP客户端和服务器首先通过Port 21端口进行建立连接，通过这个通道发送命令。客户端需要接受数据时在此端口上进行Port命令。Port命令包含了客户端用什么端口进行接受数据，在传输数据时服务器端通过自己的TCP21端口连接到客户端指定的端口进行发送数据。</p>
</li>
<li>
<p><strong>被动模式</strong></p>
<p></p>
<p>建立通道与主动模式相似，建立之后是Pasv命令。服务器收到呢Pasv命令后随机打开一个高端端口(大于1024)并且通知客户端在这个端口上进行请求，客户端连接FTP服务器此端口，通过三次握手进行建立通道，然后服务器通过这个端口进行数据的传输。</p>
</li>
<li>
<p>注意有防火墙的限制，很多防火墙限制了从外部访问发起的连接，所以防火墙和内网中的FTP很多都是不支持Pasv模式的，因此客户端无法通过防火墙来打开一个高端端口。然后很多内网的客户端无法使用Port模式进行登录FTP服务器，因为从服务器的TCP 20端口无法和内网的客户端建立一个新的连接。</p>
</li>
</ul>
<h3>SFTP</h3>
<p>然后SFTP是SSH FIle Transfer Protocol，安全的传输协议。同样FTP和SFTP有种相同的语法和功能。SFTP为SSH的其中一部分，是一种传输档案至服务器的安全方式。其实在SSH软件包中，已经包含了一个叫作SFTP的安全文件信息传输子系统，SFTP本身没有单独的守护进程，它必须使用sshd守护进程(端口号默认是22)来完成相应的连接和答复操作，所以从某种意义上来说，SFTP并不像一个服务器程序，而更像是一个客户端程序。</p>
<h3>两者区别</h3>
<ul>
<li><strong>连接方式:</strong> FTP使用TCP端口21来和服务器端进行连接，SFTP是在客户端和服务端之间通过SSH协议(TCP22端口) 建立安全连接来传输文件。</li>
<li><strong>安全性:</strong> SFTP使用加密传输认证信息和传输数据，所以SFTP相对FTP安全。</li>
<li><strong>效率：</strong> SFTP传输方式使用了加密技术，所以传输效率相对普通FTP要低一些。</li>
</ul>
<p>对于这个文件，最开始有些懵，所以就简单的介绍了一些FTP的主动、被动模式的工作流程，然后说一下SFTP是一种基于ssh安全认证的加密传输模式。然后说了一下两者在连接方式流程上、安全性上、工作效率上的不同，主要就说了这些内容。</p>
<p>然后就开始问到了JUC了，下面就开始了</p>
<h2>线程状态</h2>
<p>支付业务当中肯定会有线程的操作，那你简单说一下线程的状态是怎样的。</p>
<h2>synchronized加锁方式和底层原理</h2>
<h2>wait() sleep() 区别</h2>
<h2>线程池有哪些,自定义线程池需要哪些内容</h2>
<p>四大线程池、七大参数、拒绝策略、工作队列有哪些</p>
<h2>线程池的数据结构</h2>
<h2>队列平时如何使用,使用场景</h2>
<h2>synchronized和lock区别</h2>
<h2>数据库事务和事务的隔离界别</h2>
<blockquote>
<ul>
<li><a href="https://developer.aliyun.com/article/743691" target="_blank" rel="noopener noreferrer">MySQL事务隔离级别</a></li>
<li><a href="https://www.cnblogs.com/xrq730/p/5087378.html" target="_blank" rel="noopener noreferrer">事务及事务隔离级别</a></li>
</ul>
</blockquote>
<h3>事务原则</h3>
<ul>
<li>原子性</li>
<li>一致性</li>
<li>持久性</li>
<li>隔离性</li>
</ul>
<h3>并发下产生的问题</h3>
<ul>
<li>
<p>脏读（Dirty Read)</p>
<p>一个事务读到了另一个未提交事务修改过的数据</p>
</li>
<li>
<p>不可重复读（Non-Repeatable Read)</p>
<p>一个事务只能读到另一个已经提交的事务修改过的数据，并且其他事务每对该数据进行一次修改并提交后，该事务都能查询得到最新值。（不可重复读在读未提交和读已提交隔离级别都可能会出现）</p>
</li>
<li>
<p>幻读（Phantom）</p>
<p>一个事务先根据某些条件查询出一些记录，之后另一个事务又向表中插入了符合这些条件的记录，原先的事务再次按照该条件查询时，能把另一个事务插入的记录也读出来。（幻读在读未提交、读已提交、可重复读隔离级别都可能会出现）</p>
</li>
</ul>
<h3>数据库隔离级别</h3>
<ul>
<li>DEFAULT</li>
<li>READ_UNCOMMITTED(读未提交)</li>
<li>READ_COMMITED(读已提交)</li>
<li>REPEATABLE_READ(重复读取)</li>
<li>SERLALIZABLE(串行化)</li>
</ul>
<p></p>
<h2>泛型擦除</h2>
<h2>自定义注解及注解上参数的使用含义</h2>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="面试"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-12-10T14:02:23.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">蚂蚁集团—一面技术—面试总结</title>
    <id>https://blog.ccoder.cc/posts/2021/alipay-ji-shu-mian-one.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/alipay-ji-shu-mian-one.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<h2>1.支付公司和银行之间清结算流程是怎样的</h2>
<h2>2.如何保证银行清结算文件可信,如何确保不被篡改</h2>
<h2>3.Redis的分布式锁</h2>
<h2>4.Redis的“一主二从三哨兵”</h2>
<h2>5.如何不用db、redis、zk解决分布式锁</h2>
<h3>5.1 Map本地高可用缓存</h3>
<h3>5.2 Map缓存扩展到分布式如何保证数据一致性和高可用</h3>
<h3>5.3 Map缓存分布式如何扩容、一致性哈希、虚拟node等实施方案</h3>
<h3>5.4 Map缓存宕机重启数据持久化磁盘(RDB、AOF)时,你会如何实现</h3>
<h2>6.Redis主从同步和cluster</h2>]]></summary>
    <content type="html"><![CDATA[<h2>1.支付公司和银行之间清结算流程是怎样的</h2>
<h2>2.如何保证银行清结算文件可信,如何确保不被篡改</h2>
<h2>3.Redis的分布式锁</h2>
<h2>4.Redis的“一主二从三哨兵”</h2>
<h2>5.如何不用db、redis、zk解决分布式锁</h2>
<h3>5.1 Map本地高可用缓存</h3>
<h3>5.2 Map缓存扩展到分布式如何保证数据一致性和高可用</h3>
<h3>5.3 Map缓存分布式如何扩容、一致性哈希、虚拟node等实施方案</h3>
<h3>5.4 Map缓存宕机重启数据持久化磁盘(RDB、AOF)时,你会如何实现</h3>
<h2>6.Redis主从同步和cluster</h2>
<h2>7.ConcurrentHashMap用到了哪些锁</h2>
<h2>8.HashMap的数据扩容迁移</h2>
<ul>
<li>capacity 容量16</li>
<li>loadFactor 扩容因子0.75</li>
<li>threshold 阈值 = 容量 * 扩容因子。(put时元素超过阈值会触发扩容)</li>
</ul>
<h3>JDK7扩容机制</h3>
<ul>
<li>空参构造</li>
<li>有参构造</li>
<li>后需扩容直接容量2倍，阈值2倍。</li>
<li>需要注意首次put时，先触发扩容初始化，然后存入数据，判断是否需要扩容。</li>
<li>非首次操作，不进行触发扩容初始化，直接存入数据，然后判断是否需要扩容。</li>
<li>元素迁移
<ul>
<li>遍历每一个entity,重新计算hash，找到新的位置使用头插法。</li>
<li>头插法，新旧链表元素位置会发生改</li>
<li>元素迁移过程中，并发情况下会触发死循环(无限链表反转)</li>
</ul>
</li>
</ul>
<h3>JDK8扩容机制</h3>
<ul>
<li>实现以2的幂次方扩容</li>
<li>entity在扩容时，要么在原位置，要么在原长度+原位置的位置上。</li>
<li>JDK8元素迁移是正序的，不会发生链表转置问题。</li>
<li>如果entity内元素超过8个,链表转换为红黑树，增加查询效率。</li>
</ul>
<h2>9.如何设计去中心化存储(分布式缓存存储)</h2>
<h2>10.RabbitMQ 如何实现分布式事务</h2>
<h2>11.分布式事务中的2PC和TCC</h2>
<h3>事务ACID</h3>
<ul>
<li>事务必须严格遵循ACID原则
<ul>
<li>原子性(Atomicity) 事务内所有操作必须是原子化不可拆分的，要么执行成功，要么执行失败</li>
<li>一致性(Consistency) 数据完整性的约束，不会存在中间状态的数据</li>
<li>隔离性(Isolation) 多个事务在并发状态下不会进行相互干扰，一个事务内的数据相对于其他事务来说是隔离的</li>
<li>持久性(Durability) 事务执行完成后数据便永久保存，不会因为故障或者其他操作对该事务结果造成影响。</li>
</ul>
</li>
</ul>
<h3>分布式事务</h3>
<p>分布式事务顾名思义是分布在不同节点应用上的事务，其实是由多个本地事务组成的，无法满足ACID原则，那么就需要系列解决方案</p>
<ul>
<li>
<p>2PC(二阶段提交)</p>
<ul>
<li>2PC是一种强一致性设计，引入了事务的协调者的角色来协调管理各个参与者(本地事务资源)的提交和回滚。并且2PC分别是准备(投票)和提交两阶段。</li>
<li>2PC是一种同步阻塞的,无论提交或者回滚都需要协调者知道所有参与者都有响应才会进行下一步操作，当然一阶段时的协调者超时机制会保证有参与者超时或Down掉时,进行通知所有参与者回滚提交。</li>
<li>协调者单点问题,存在故障时可通过选举得到新的协调者。</li>
</ul>
</li>
<li>
<p>3PC</p>
<ul>
<li>参与者增加了超时机制</li>
<li>准备阶段(CanCommit)、预提交阶段(PreCommit)、提交阶段(DoCommit)</li>
<li>2PC 3PC均是数据库层面的,下面TCC是从业务层面来解决分布式事务</li>
</ul>
</li>
<li>
<p>TCC(Try-Comfirm-Cancel)</p>
<p>TCC是一种尝试性执行,若所有参与结点都有事务执行的条件，那么直接执行事务。否则Cancel回滚操作。</p>
<ul>
<li>Try-预留,事务执行资源的预留和锁定</li>
<li>Confirm-确认操作,这一步执行成功</li>
<li>Cancel-撤销操作,对预留阶段锁定的资源进行撤销。</li>
<li>对业务的操作入侵比较大,耦合性高,对于Try和Cancel可能需要重试</li>
<li>需要业务系统保证操作的幂等性</li>
<li>从业务角度的实现方案,因此可以跨数据库、跨业务系统。</li>
</ul>
</li>
<li>
<p>本地消息表</p>
<p>本地消息表是利用各系统本地事务来实现分布式事务。</p>
<ul>
<li>业务系统的执行和消息均放入本地消息表中,确保本地业务执行和消息表的操作在一个事务中。</li>
<li>不尝机制重试读取本地消息表,调用远程应用操作。</li>
<li>需要加入重试机制、最大执行次数、报警机制。</li>
<li>本地消息表容忍数据暂时不一致，期望数据的最终一致性。</li>
</ul>
</li>
<li>
<p>消息事务</p>
<p>消息事务的执行实现方案也是数据最终一致性。</p>
<ul>
<li>第一步先给 Broker 发送事务消息即半消息，发送成功后发送方再执行本地事务。</li>
<li>本地事务的结果向 Broker 发送 Commit 或者 RollBack 命令。</li>
<li>提供反事务查询接口,超时时会根据该接口判断事务是否执行成功,然后在执行Commit或Rollback操作。</li>
</ul>
</li>
<li>
<p>最大努力通知</p>
<p>对于时间不敏感的业务，短信、邮件通知等。尽最大努力进行推送消息保证事务数据的最终一致性。</p>
</li>
</ul>
<h2>12.简单介绍一下RabbitMQ的Push和Pull模式</h2>
<h3>Push</h3>
<ul>
<li>服务端主动推送消息给客户端,及时性较高.</li>
<li>若客户端处理能力较弱时会产生消息堆积、处理缓慢、甚至于崩溃。</li>
<li>避免该情况产生，需要根据客户端消费能力做流控(rabbitMQ-Qos).</li>
<li>服务端需要维护每次推送消息的状态，推送失败后需要进行重试。</li>
</ul>
<h3>pull</h3>
<ul>
<li>客户端可根据自身性能进行消费。</li>
<li>数据传输失败时消息不会丢失,只需客户端重新从服务端进行拉取即可。</li>
<li>确保客户端主动到服务端拉取消息的时间间隔设置合适，避免高频拉取对服务端造成压力。间隔时间过长会造成数据延迟和堆积。</li>
</ul>
<h3>不同业务场景选择</h3>
<ul>
<li>服务端消息过大,客户端对消息处理逻辑流程复杂,消费性能较弱时可选择pull模式。</li>
<li>对于数据实时性要求较高时，可采用push进行实时推送。</li>
</ul>
<h2>13.索引如何使用的</h2>
<h3>13.1 索引失效</h3>
<ul>
<li>MySQL引擎结算全表扫描更快</li>
<li>Where中存在函数</li>
<li>Where中索引列存在运算</li>
<li>需要类型转换时</li>
<li>联合索引时未使用左字段(联合索引最左原则)</li>
<li>使用like关键字时 第一个字符<code>%</code>开始索引失效</li>
<li>使用or时必须两边字段全有索引</li>
</ul>
<h2>14.索引下推和索引覆盖</h2>
<blockquote>
<ul>
<li><a href="https://www.jianshu.com/p/bdc9e57ccf8b" target="_blank" rel="noopener noreferrer">索引覆盖和索引覆盖</a></li>
</ul>
</blockquote>
<p>当sql语句<code>select password from table where username = 'cong'</code> 的所求查询字段（select列）和查询条件字段（where子句）全都包含在一个索引<code>(username,password)</code>中，可以直接使用索引查询而不需要回表。这就是<strong>覆盖索引</strong>，通过使用覆盖索引，可以减少搜索树的次数，是常用的性能优化手段。</p>
<ul>
<li>
<p>联合索引最左原则: 联合索引的多个字段中，只有当查询条件为联合索引的一个字段时，查询才能使用该索引。</p>
</li>
<li>
<p>索引可以用于查询条件字段为索引字段，根据字段值最左若干个字符进行的模糊查询。<code>username like %cong</code></p>
</li>
<li>
<p>需要回表查询的全行数据比较少，这就是mysql的索引下推。</p>
</li>
</ul>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="面试"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-12-22T19:39:14.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">蚂蚁集团—二面技术(直属领导)—面试总结</title>
    <id>https://blog.ccoder.cc/posts/2021/alipay-ji-shu-mian-two.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/alipay-ji-shu-mian-two.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<h2>1.介绍一下你在公司的职能</h2>
<p>方面面试官了解目前岗位职能，日常工作(业务+技术点)</p>
<h2>2.介绍一个你觉得最有价值的项目</h2>
<h3>2.1 业务层面介绍(业务栈)</h3>
<h3>2.2 技术层面介绍(技术栈)</h3>
<p>这里可以引入自己非常熟悉的知识点，引导面试官下一个问题往这上面提问。</p>
<h2>3.(前面引入)分布式事务在业务上如何落地的</h2>
<h2>4.(前面引入)Redis和DB一致性问题的解决方案</h2>
<blockquote>
<ul>
<li><a href="https://www.its404.com/article/alionsss/107451485" target="_blank" rel="noopener noreferrer">分布式缓存一致性</a></li>
</ul>
</blockquote>]]></summary>
    <content type="html"><![CDATA[<h2>1.介绍一下你在公司的职能</h2>
<p>方面面试官了解目前岗位职能，日常工作(业务+技术点)</p>
<h2>2.介绍一个你觉得最有价值的项目</h2>
<h3>2.1 业务层面介绍(业务栈)</h3>
<h3>2.2 技术层面介绍(技术栈)</h3>
<p>这里可以引入自己非常熟悉的知识点，引导面试官下一个问题往这上面提问。</p>
<h2>3.(前面引入)分布式事务在业务上如何落地的</h2>
<h2>4.(前面引入)Redis和DB一致性问题的解决方案</h2>
<blockquote>
<ul>
<li><a href="https://www.its404.com/article/alionsss/107451485" target="_blank" rel="noopener noreferrer">分布式缓存一致性</a></li>
</ul>
</blockquote>
<h3>4.1 缓存读写策略</h3>
<ul>
<li>
<p>Cache Aside Pattern（旁路缓存模式)</p>
<ul>
<li>
<p>读</p>
<p>读Cache,存在直接返回,不存在再从DB中读取并且放回Cache</p>
</li>
<li>
<p>写</p>
<p>先更新DB,然后直接删除Cache</p>
</li>
</ul>
</li>
<li>
<p>Read/Write Through Pattern（读写穿透）</p>
<ul>
<li>
<p>读</p>
<p>读Cache,存在直接返回,不存在再从DB中读取并且放回Cache</p>
</li>
<li>
<p>写</p>
<p>读Cache,不存在时直接更新DB。存在时更新Cache,然后进行Cache和DB同步更新。</p>
</li>
</ul>
</li>
<li>
<p>Write Behind Pattern（异步缓存写入)</p>
<p>和读写穿透很相似,都是由Cache负责Cache和DB的读写更新.读写穿透是同步更新Cache和DB,但是异步缓存写入是只更新Cache,不直接更新DB,才用异步批量的方式更新DB。</p>
<p>此方式适合一些写入频繁，但是数据一致性要求不高场景。</p>
</li>
</ul>
<h3>4.2 Cache和DB操作顺序</h3>
<ul>
<li>先更新Cache,再更新DB</li>
</ul>
<p>无法保证两次更新均成功,可能存在缓存中为新数据,但DB中仍然是旧数据</p>
<ul>
<li>先更新DB,再更新缓存</li>
</ul>
<p>并发情况下两个线程进行操作可能导致Cache和DB数据不一致问题。</p>
<blockquote>
<p>假设请求 A 先操作数据库，请求 B 后操作数据库，但是可能存在请求 B 先写缓存，请求 A 后写缓存的情况，从而导致数据库与缓存之间的数据不一致。</p>
</blockquote>
<ul>
<li>先写DB,再删除Cache</li>
</ul>
<p>业务如何保证写DB和删除Cache为原子操作,否则会出现写入DB但是Cache未做删除操作，导致数据一致性问题。</p>
<blockquote>
<ul>
<li>请求1从DB中读取数据A数据</li>
<li>请求2写操作更新DB中A数据,并且删除Cache中A数据</li>
<li>请求1将数据A写入Cache</li>
</ul>
</blockquote>
<ul>
<li>先删除Cache,再更新DB</li>
</ul>
<p>先删Cache,在写入DB之前，若有另外请求读取Cache未命中时,读取DB中‘旧’值将其更新回Cache,此时Cache中为旧值,DB中为新值。</p>
<blockquote>
<ul>
<li>请求1将Cache中数据A删除</li>
<li>请求2从Cache中读取A数据时未命中,查询DB并将其回写到Cache中</li>
<li>请求1继续将DB中A数据更新</li>
</ul>
</blockquote>
<h3>4.3 保证一致性解决方案</h3>
<ul>
<li>采用延时双删策略</li>
<li>异步更新缓存策略(订阅binlog的同步机制)</li>
<li>混合存储优化方案</li>
</ul>
<h2>5.说一个你最了解中间件(Dubbo)</h2>
<h3>5.1 Dubbo设计观念(插件+微内核)</h3>
<h3>5.2 SPI</h3>
<h3>5.3 RPC调用原理</h3>
<h3>5.4 Dubbo序列化方式是否存在问题</h3>
<h2>6.解决的生产问题</h2>
<h3>6.1 Dubbo的热加载问题(版本bug)</h3>
<h3>6.2 单号生成方式导致问题</h3>
<p>这个问题可以引入分布式下单号生成的几种方案。</p>
<h2>7.消息队列是怎么使用的</h2>
<h3>7.1 推拉模式</h3>
<p>消息队列核心应用场景:削峰、异步和解耦。那么在消息队列中消息模式有推拉模式。</p>
<ul>
<li>
<p>Push模式</p>
<p>Push模式是服务端根据用户需要，有目的、定时将数据推送到客户端。</p>
<ul>
<li>[优点]对客户端要求第,方便客户端获取数据。</li>
<li>[优点]及时性好，服务端及时向客户端推送消息，吞吐量大。</li>
<li>[缺点]不能够保证发送成功,push采用广播模式</li>
<li>[缺点]没有消息状态跟踪，客户端是否成功接收到信息无法得知，存在消息丢失问题。</li>
<li>[缺点]针对性差,无法满足客户端定制化需求。</li>
<li>[缺点]客户端消费能力弱时，容易造成消息对接</li>
</ul>
</li>
<li>
<p>Pull模式</p>
<p>客户端主动向服务端获取信息。</p>
<ul>
<li>[优点]针对性强，可满足客户端定制化需求。</li>
<li>[优点]信息传输量小,该次网络请求中只有客户端请求和服务端响应数据</li>
<li>[优点]服务端压力较小,只是被动地响应客户端请求。客户端根据自身消费能力拉取。</li>
<li>[缺点]实时性较差,对于服务端实时更新数据客户端无法感知,无法获得实时数据</li>
<li>[缺点]对客户端要求较高</li>
</ul>
</li>
</ul>
<h3>7.2 消息丢失问题(分布式事务、本地消息表)</h3>
<h3>7.3 用过几种消息队列(如果用过可以拓展比较)</h3>
<h2>8.看过哪些中间件源码(Dubbo)</h2>
<h2>9.对公司的整体技术架构的理解</h2>
<h2>10.职业发展规划</h2>
<h2>11.为什么要离职</h2>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="面试"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-12-15T22:03:14.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">支付宝-国际事业部-高级Java工程师</title>
    <id>https://blog.ccoder.cc/posts/2021/alipay-kuajin-jishumian-one.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/alipay-kuajin-jishumian-one.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<h2>1.笔试题</h2>
<h3>1.1大文件查找前100个最大的数字</h3>
<blockquote>
<p>有一个文本文件(data.txt)里面每行为一个数字切文件预计有100W行左右,请以最快的速度在一台主机4核cpu/1G内存的主机上找出前100个最大的数字，并且输出其在文件所在行。
注意：请尽量提供该程序在生产运行所需全部信息。</p>
</blockquote>
<h3>1.2实现LRU算法(禁用LinkedHashMap)</h3>
<blockquote>
<p>LRU(Least recently used 最近最少使用)算法根据数据的历史访问记录来进行淘汰数据，其核心思想是“如果数据最近被访问过，那么将来被访问的几率也更高”
设计一个实现以下接口的LRU缓存方法,不能使用LinkedHashMap.</p>
</blockquote>]]></summary>
    <content type="html"><![CDATA[<h2>1.笔试题</h2>
<h3>1.1大文件查找前100个最大的数字</h3>
<blockquote>
<p>有一个文本文件(data.txt)里面每行为一个数字切文件预计有100W行左右,请以最快的速度在一台主机4核cpu/1G内存的主机上找出前100个最大的数字，并且输出其在文件所在行。
注意：请尽量提供该程序在生产运行所需全部信息。</p>
</blockquote>
<h3>1.2实现LRU算法(禁用LinkedHashMap)</h3>
<blockquote>
<p>LRU(Least recently used 最近最少使用)算法根据数据的历史访问记录来进行淘汰数据，其核心思想是“如果数据最近被访问过，那么将来被访问的几率也更高”
设计一个实现以下接口的LRU缓存方法,不能使用LinkedHashMap.</p>
</blockquote>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-java"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> public</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> interface</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> LruCache</span><span style="--shiki-light:#C18401;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">K</span><span style="--shiki-light:#C18401;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> V</span><span style="--shiki-light:#C18401;--shiki-dark:#ABB2BF">></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    /**</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * Set the capacity of the total cache num</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * </span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * </span><span style="--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic">@param</span><span style="--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> capacity</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     *            capacity</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     */</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> setCapacity</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> capacity</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    /**</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * Update cache according to LRU definition. This time complexity of this method should be O(1).</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * </span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * </span><span style="--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic">@param</span><span style="--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> cacheKey</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     *            key</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * </span><span style="--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic">@param</span><span style="--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> cacheValue</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     *            value</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     */</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> put</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">K</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> cacheKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">V</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> cacheValue</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    /**</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * 获取元素</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * </span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * </span><span style="--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic">@param</span><span style="--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> cacheKey</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     *            元素key</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     * </span><span style="--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic">@return</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> value</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">     */</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">    V</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">K</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> cacheKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>2.面试题</h2>
<h3>跳表SkipList和ConcurrentSkipListMap源码分析</h3>
<h3>JDK动态代理实现原理</h3>
<h3>Spring AOP 实现原理</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/liantdev/p/10132680.html" target="_blank" rel="noopener noreferrer">Sring AOP 实现原理</a></li>
<li><a href="https://blog.csdn.net/wyl6019/article/details/80136000" target="_blank" rel="noopener noreferrer">Spring AOP实现原理简介</a></li>
</ul>
</blockquote>
<h3>Spring Bean 的创建流程</h3>
<blockquote>
<ul>
<li><a href="https://blog.csdn.net/blacksnow_/article/details/112187019" target="_blank" rel="noopener noreferrer">Spring单例Bean创建流程</a></li>
<li><a href="https://www.jianshu.com/p/1dec08d290c1" target="_blank" rel="noopener noreferrer">Spring Bean的生命周期</a></li>
</ul>
</blockquote>
<h3>CAP原则</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/chihirotan/p/11366394.html" target="_blank" rel="noopener noreferrer">Eureka和Zookeper区别</a></li>
</ul>
</blockquote>
<h3>分布式系统接口幂等性设计</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/jack87224088/p/8688948.html" target="_blank" rel="noopener noreferrer">接口幂等性设计实现</a></li>
</ul>
</blockquote>
<h3>MySQL索引数据结构</h3>
<blockquote>
<ul>
<li><a href="https://blog.csdn.net/kongmin_123/article/details/82055901" target="_blank" rel="noopener noreferrer">MySQL索引数据结构</a></li>
<li><a href="https://www.cnblogs.com/luyucheng/p/6289714.html" target="_blank" rel="noopener noreferrer">MySQL索引类型</a></li>
</ul>
</blockquote>
<h3>Redis缓存雪崩和穿透</h3>
<blockquote>
<ul>
<li><a href="https://baijiahao.baidu.com/s?id=1619572269435584821&amp;wfr=spider&amp;for=pc" target="_blank" rel="noopener noreferrer">Reids缓存穿透、雪崩、击穿</a></li>
<li><a href="https://blog.csdn.net/a898712940/article/details/116212825" target="_blank" rel="noopener noreferrer">缓存穿透、缓存击穿、缓存雪崩解决方案</a></li>
<li><a href="https://segmentfault.com/a/1190000039300423" target="_blank" rel="noopener noreferrer">缓存雪崩、击穿、穿透解决方案</a></li>
</ul>
</blockquote>
<h3>Redis分布式锁</h3>
<blockquote>
<ul>
<li><a href="https://segmentfault.com/a/1190000038988087" target="_blank" rel="noopener noreferrer">Redis分布式锁实现</a></li>
</ul>
</blockquote>
<h3>线程池</h3>
<blockquote>
<ul>
<li><a href="https://blog.csdn.net/lchq1995/article/details/85230399" target="_blank" rel="noopener noreferrer">线程池工作原理</a></li>
</ul>
</blockquote>
<h3>高并发解决方案</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/alex96/p/12152388.html" target="_blank" rel="noopener noreferrer">Java高并发解决方案</a></li>
</ul>
</blockquote>
<h3>CAS</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/toov5/p/9858129.html" target="_blank" rel="noopener noreferrer">CAS无锁机制原理</a></li>
</ul>
</blockquote>
<h3>Java锁的种类</h3>
<blockquote>
<ul>
<li><a href="https://blog.csdn.net/nalanmingdian/article/details/77800355" target="_blank" rel="noopener noreferrer">Java锁的种类</a></li>
<li><a href="https://blog.csdn.net/oheg2010/article/details/89850181" target="_blank" rel="noopener noreferrer">JUC锁的分类</a></li>
<li><a href="https://blog.csdn.net/weixin_40616523/article/details/86419754" target="_blank" rel="noopener noreferrer">分段锁理解</a></li>
<li><a href="https://blog.csdn.net/qwe123147369/article/details/109601929" target="_blank" rel="noopener noreferrer">ConcurrentHashMap锁了解</a></li>
<li><a href="https://blog.csdn.net/weixin_48499022/article/details/107617132" target="_blank" rel="noopener noreferrer">为什么ConcurrentHashMap是线程安全的</a></li>
</ul>
</blockquote>
<h3>hashCode和equals区别</h3>
<blockquote>
<ul>
<li><a href="https://blog.csdn.net/QGhurt/article/details/106902777" target="_blank" rel="noopener noreferrer">hashCode和equal区别</a></li>
</ul>
</blockquote>
<h3>HashMap 数据结构</h3>
<blockquote>
<ul>
<li><a href="https://blog.csdn.net/qq_43370771/article/details/111353046" target="_blank" rel="noopener noreferrer">HashMap 底层实现</a></li>
</ul>
</blockquote>
<h3>NIO、AIO、BIO区别</h3>
<blockquote>
<ul>
<li><a href="https://blog.csdn.net/m0_38109046/article/details/89449305" target="_blank" rel="noopener noreferrer">BIO、NIO、AIO总结</a></li>
<li><a href="https://www.cnblogs.com/areyouready/p/7813135.html" target="_blank" rel="noopener noreferrer">IO和NIO区别</a></li>
</ul>
</blockquote>
<h3>布隆过滤器</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/qdhxhz/p/11237246.html" target="_blank" rel="noopener noreferrer">布隆过滤器原理</a></li>
</ul>
</blockquote>
<h3>MySQL日志</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/rinack/p/9595370.html" target="_blank" rel="noopener noreferrer">binlog日志三种模式选择和配置</a></li>
</ul>
</blockquote>
<h3>热点账户</h3>
<blockquote>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/210879230" target="_blank" rel="noopener noreferrer">热点账户高并发记账方案</a></li>
</ul>
</blockquote>
<h3>分布式事务解决方案</h3>
<blockquote>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/183753774" target="_blank" rel="noopener noreferrer">六种分布式事务解决方案</a></li>
</ul>
</blockquote>
<h3>Redis底层数据结构</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/ysocean/p/9080942.html#_label1" target="_blank" rel="noopener noreferrer">Redis底层数据结构</a></li>
<li><a href="https://juejin.cn/post/6844903644798664712" target="_blank" rel="noopener noreferrer">Redis数据结构基础</a></li>
<li><a href="https://segmentfault.com/a/1190000040102333" target="_blank" rel="noopener noreferrer">Redis几种数据结构解析</a></li>
</ul>
</blockquote>
<h3>MySQL 事务隔离界别</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/digdeep/archive/2015/11/16/4968453.html" target="_blank" rel="noopener noreferrer">MySQL事务隔离界别</a></li>
<li><a href="https://xie.infoq.cn/article/8f8ec3f8baa47ae0ca42d3481" target="_blank" rel="noopener noreferrer">MySQL事务、日志、锁、索引</a></li>
</ul>
</blockquote>
<h3>彻底弄懂MySQL日志</h3>
<blockquote>
<ul>
<li><a href="https://www.cxyxiaowu.com/10740.html" target="_blank" rel="noopener noreferrer">MySQL日志|事务隔离</a></li>
</ul>
</blockquote>
<h3>接口性能优化方案</h3>
<blockquote>
<ul>
<li><a href="https://cloud.tencent.com/developer/article/1637579" target="_blank" rel="noopener noreferrer">接口性能优化实践方案</a></li>
</ul>
</blockquote>
<h3>网关限流</h3>
<blockquote>
<ul>
<li><a href="https://segmentfault.com/a/1190000020745218" target="_blank" rel="noopener noreferrer">限流算法对比、网关限流</a></li>
</ul>
</blockquote>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="面试"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-12-28T18:18:49.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">欢聚集团(Joyy)—Java海外支付岗位—技术面(一面)总结</title>
    <id>https://blog.ccoder.cc/posts/2021/joyy-ji-shu-mian-one.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/joyy-ji-shu-mian-one.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<h2>笔试题(牛客网)</h2>
<p>给定一个房间连接,准时参加牛客网面试题笔试。</p>
<ul>
<li>leetcode <a href="https://leetcode-cn.com/problems/binary-tree-preorder-traversal/" target="_blank" rel="noopener noreferrer">144-二叉树的前序遍历</a></li>
<li>牛客网 <a href="https://www.nowcoder.com/questionTerminal/501fb3ca49bb4474bf5fa87274e884b4" target="_blank" rel="noopener noreferrer">求二叉树的前序遍历</a></li>
</ul>]]></summary>
    <content type="html"><![CDATA[<h2>笔试题(牛客网)</h2>
<p>给定一个房间连接,准时参加牛客网面试题笔试。</p>
<ul>
<li>leetcode <a href="https://leetcode-cn.com/problems/binary-tree-preorder-traversal/" target="_blank" rel="noopener noreferrer">144-二叉树的前序遍历</a></li>
<li>牛客网 <a href="https://www.nowcoder.com/questionTerminal/501fb3ca49bb4474bf5fa87274e884b4" target="_blank" rel="noopener noreferrer">求二叉树的前序遍历</a></li>
</ul>
<h2>首先是简单的自我介绍</h2>
<p>面试官会根据简历和自我介绍内容进行提问，找到一个切入口。
首先是提问Java的一些内容。</p>
<h2>JVM内存模型知道吗？说一下你对JVM内存模型的理解。</h2>
<p>主要有一个图很经典。脑海里面要有这个图。

class文件-&gt;类加载器(classloader)-&gt;加载这个图,哪些内存区间是私有独立的，哪些是线程共享的。</p>
<h2>Java类加载器</h2>
<p>主要从类加载流程(加载、验证、解析、初始化)几个过程说一下。
继续说一下经典的双亲委派模型</p>
<ul>
<li>Bootstrap ClassLoader</li>
<li>Extension ClassLoader</li>
<li>Application ClassLoader</li>
<li>Custom ClassLoader</li>
</ul>
<p>这几个加载器有一个图很经典脑海里面得有印象。
还有双亲委派模型的优势是哪些？
线程上下文加载器是如何对双亲委派模型进行破坏的。</p>
<h2>说一下HashMap初始化的时候16和0.75是指什么</h2>
<ul>
<li>capacity 即容量，默认16。</li>
<li>loadFactor 加载因子，默认是0.75</li>
<li>threshold 阈值。阈值=容量*加载因子。默认12。当元素数量超过阈值时便会触发扩容。</li>
</ul>
<p>这个要说一下HashMap的扩容机制。</p>
<ul>
<li>什么时候触发的扩容</li>
<li>JDK7中的扩容机制、元素迁移</li>
<li>JDK8中的扩容机制、元素迁移
然后还可以扩展说一下HashMap的底层原理、数据结构。</li>
</ul>
<h2>线程的几个状态</h2>
<p>这个脑海里面也有个线程生命周期的图。New、Runnable、Running、Terminated、Timed_Waiting、Blocked、Waiting等。

在线程转移图中的各个状态是如何跃迁转移的。涉及到哪些方法，在什么时候触发。</p>
<h2>说说你对线程池的了解</h2>
<p>几个固定的创建方法、七大核心参数、四个拒绝策略这些都是需要提出来的。</p>
<ul>
<li>ExecutorService中四大线程池创建方法，各自应用场景。</li>
<li>线程池七大参数:<code>corePoolSize</code> <code>maximunPoolSize</code> <code>keepAliveTime</code> <code>unit</code> <code>workQueue</code> <code>threadFactory</code> <code>handler</code></li>
<li>四大拒绝策略: <code>AbortPolicy</code> <code>DiscardPolicy</code> <code>DiscardOldestPolicy</code>  <code>CallerRunsPolicy</code></li>
</ul>
<h2>说说数据库索引</h2>
<blockquote>
<ul>
<li><a href="https://mp.weixin.qq.com/s/_bk2JVOm2SkXfdcvki6-0w" target="_blank" rel="noopener noreferrer">MySQL索引</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/350863953" target="_blank" rel="noopener noreferrer">MySQL高频问题</a></li>
</ul>
</blockquote>
<h3>索引的优缺点</h3>
<h3>索引如何优化、为什么会失效</h3>
<h3>聚簇索引、覆盖索引</h3>
<h3>联合索引、最左前缀匹配</h3>
<h3>索引下推、查询优化</h3>
<h2>分布式事务</h2>
<blockquote>
<ul>
<li>参考<a href="http://icyfenix.cn/architect-perspective/general-architecture/transaction/" target="_blank" rel="noopener noreferrer">凤凰架构-事务处理</a></li>
<li><a href="https://segmentfault.com/a/1190000040321750" target="_blank" rel="noopener noreferrer">分布式事务经典七中解决方案</a></li>
</ul>
</blockquote>
<h3>2PC/TCC/3PC</h3>
<h3>SAGA 事务</h3>
<h3>本地消息表+补偿事件</h3>
<h3>异常处理(防空回滚，幂等，防悬挂)</h3>
<h3>子事务屏障/原理</h3>
<h2>RabbitMQ 如何保证消息可靠传递</h2>
<h2>Synchronized和Lock锁</h2>
<blockquote>
<ul>
<li><a href="https://segmentfault.com/a/1190000022456039" target="_blank" rel="noopener noreferrer">Java锁Lock的种类</a></li>
</ul>
</blockquote>
<h3>Synchronized和Lock区别和认识</h3>
<h3>锁的类型</h3>
<p>|锁/类型|公平/非公平锁|可重入/不可重入锁|共享/独享锁|乐观/悲观锁|
|</p>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="面试"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-12-11T18:41:16.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">欢聚集团(Joyy)—Java海外支付岗位—业务技术面(二面+三面)总结</title>
    <id>https://blog.ccoder.cc/posts/2021/joyy-ye-wu-mian-two.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/joyy-ye-wu-mian-two.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<h2>说说如何实现一个渠道路由系统</h2>
<h3>路由策略落库方案</h3>
<p>可以往规则引擎+Drools进行靠,给出一个合理的解决方案,包括如何快速响应、通用、可动态配置。</p>
<h3>渠道评分规则</h3>
<ul>
<li>交易卡组织</li>
<li>对公对私</li>
<li>交易费率(单笔、百分比、交易额度阶梯)</li>
<li>渠道历史成功率/赔付率</li>
<li>渠道结算周期</li>
</ul>
<p>从上述维度进行系列路由、并且按照一定维度权重进行评分，给出一个最优渠道+部分备用渠道，支付失败时进行切换备用渠道，提高整体支付成功率，提升用户体验度。</p>]]></summary>
    <content type="html"><![CDATA[<h2>说说如何实现一个渠道路由系统</h2>
<h3>路由策略落库方案</h3>
<p>可以往规则引擎+Drools进行靠,给出一个合理的解决方案,包括如何快速响应、通用、可动态配置。</p>
<h3>渠道评分规则</h3>
<ul>
<li>交易卡组织</li>
<li>对公对私</li>
<li>交易费率(单笔、百分比、交易额度阶梯)</li>
<li>渠道历史成功率/赔付率</li>
<li>渠道结算周期</li>
</ul>
<p>从上述维度进行系列路由、并且按照一定维度权重进行评分，给出一个最优渠道+部分备用渠道，支付失败时进行切换备用渠道，提高整体支付成功率，提升用户体验度。</p>
<h2>银行清结算流程</h2>
<h2>如何保证各渠道解析脚本的安全性(稳步迭代)</h2>
<h2>与银行渠道的资金对账流程</h2>
<h2>接入一个银行渠道需要考虑哪些因素</h2>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="面试"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-12-15T22:43:08.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">支付行业常用名词整理</title>
    <id>https://blog.ccoder.cc/posts/2021/zhi-fu-hang-ye-zhuan-yong-ming-ci.html</id>
    <link href="https://blog.ccoder.cc/posts/2021/zhi-fu-hang-ye-zhuan-yong-ming-ci.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<h2>1.备付金</h2>
<ul>
<li><strong>客户备付金</strong></li>
</ul>
<p>是指支付机构为办理客户委托的支付业务而实际收到的预收待付货币资金。</p>
<ul>
<li><strong>备付金存管银行</strong></li>
</ul>
<p>备付金存管银行是指可以为支付机构办理客户备付金的跨行收付业务，并负责对机构存放在所有备付金银行的客户备付金信息进行归集、核对与监管的备付金银行。<a href="http://www.gov.cn/zhengce/zhengceku/2021-01/23/content_5582141.htm" target="_blank" rel="noopener noreferrer">《<strong>非银行支付机构客户备付金存管办法</strong>》</a></p>]]></summary>
    <content type="html"><![CDATA[<h2>1.备付金</h2>
<ul>
<li><strong>客户备付金</strong></li>
</ul>
<p>是指支付机构为办理客户委托的支付业务而实际收到的预收待付货币资金。</p>
<ul>
<li><strong>备付金存管银行</strong></li>
</ul>
<p>备付金存管银行是指可以为支付机构办理客户备付金的跨行收付业务，并负责对机构存放在所有备付金银行的客户备付金信息进行归集、核对与监管的备付金银行。<a href="http://www.gov.cn/zhengce/zhengceku/2021-01/23/content_5582141.htm" target="_blank" rel="noopener noreferrer">《<strong>非银行支付机构客户备付金存管办法</strong>》</a></p>
<ul>
<li><strong>备付金合作银行</strong></li>
</ul>
<p>是指可以为支付机构办理客户备付金的收取和本银行支取业务，并负责对支付机构存放在本银行的客户备付金进行监管的备付金银行。</p>
<ul>
<li><strong>备付金协议</strong></li>
</ul>
<p>是指支付机构与备付金银行或其授权的一个进内分支机构签订的，约定双方的权利、义务和责任的协议。该协议应当约定支付机构从备付金银行划转客户备付金的支付指令，以及客户备付金发生损失时双方应当承担的偿付责任和相关偿付方式。</p>
<ul>
<li><strong>备付金专用存款账户</strong></li>
</ul>
<p>是指支付机构在备付金银行开立的专户存放客户备付金的活期存款账户，包括备付金存管账户、备付金收付账户和备付金汇缴账户。</p>
<ul>
<li><strong>备付金存管账户</strong></li>
</ul>
<p>支付机构在备付金银行开立的，可以以现金形式接收客户备付金、以银行转账方式办理客户备付金收取和支出业务的专用存款账户。支付机构在备付金存管授权行或其辖属机构开立的备付金存管账户称为备付金主存管账户。</p>
<ul>
<li><strong>备付金收付账户</strong></li>
</ul>
<p>是支付机构在备付金合作银行开立的，可以以现金形式或以银行转账方式接收客户备付金、以银行资金内部划转方式办理客户备付金支取业务的专用存款账户。支付机构备付金收付账户应该开立在备付金合作授权行。</p>
<ul>
<li><strong>备付金汇缴账户</strong></li>
</ul>
<p>是支付机构在备付金银行开立的可以以现金形式接收或以本银行资金内部划转方式接收客户备付金的专用存款账户。备付金银行应当于每日营业终了前，将备付金汇缴账户内的资金全额划转至支付机构的备付金存管账户或在同一备付金合作银行开立备付金收付账户。支付机构可以通过备付金汇缴账户将客户备付金直接退回至原资金转出账户。</p>
<ul>
<li><strong>客户备付金日均余额</strong></li>
</ul>
<p>是指备付金存管银行的法人机构根据最近90日内支付机构每日日终的客户备付金总量计算的平均值。(非金融机构支付服务管理办法)</p>
<h2>2.机构和商户</h2>
<ul>
<li><strong>支付机构</strong></li>
<li><strong>收单机构</strong></li>
</ul>
<p>与商户签有协议或为持卡人提供服务，直接或间接凭交易单据(包括电子单据或纸质单据)参加交换的清算会员单位。</p>
<ul>
<li><strong>收单机构的特约商户</strong></li>
<li><strong>实体特约商户</strong></li>
<li><strong>特约商户</strong></li>
</ul>
<p>是指与收单机构签订银行卡受理协议、按约定受理银行卡并委托收单机构为其完成交易资金结算的企事业单位、个体工商户或其他组织，以及按照国家工商行政管理机关有关规定，开展网络商品交易等经营活动的自然人。</p>
<ul>
<li><strong>网络支付机构</strong></li>
<li><strong>网络支付机构的特约商户</strong></li>
<li><strong>银行卡清算机构</strong></li>
<li><strong>预付卡机构</strong></li>
<li><strong>预付卡的特约商户</strong></li>
</ul>
<h2>3.POS</h2>
<ul>
<li><strong>POS</strong></li>
<li><strong>T+0 POS机</strong></li>
<li><strong>T+1 POS机</strong></li>
<li><strong>mPOS</strong></li>
<li><strong>POS一清机</strong></li>
<li><strong>POS二清机</strong></li>
<li><strong>POS非法移机</strong></li>
<li><strong>POS签购单</strong></li>
<li><strong>POS专业化办事公司</strong></li>
<li><strong>直连POS</strong></li>
</ul>
<p>指POS终端直接与银联系统相连接，当发生POS消费时，此交易信息先送至银联主机系统，由银联系统自动判断后直接送相关的发卡银行，然后信息再沿路返回。</p>
<ul>
<li><strong>智能POS</strong></li>
</ul>
<p>一个基于互联网的商户智能终端,一个帮商户实现智能化,互联网化,大数据化经营的全新POS。拥有融合收款、卡券营销、微商城、消息管理、经营统计分析等多项功能。</p>
<h2>4.交易类型</h2>
<ul>
<li><strong>AA收款</strong></li>
<li><strong>API接口支付</strong></li>
<li><strong>B2B网银支付</strong></li>
<li><strong>IVR支付</strong></li>
<li><strong>本代本收单</strong></li>
<li><strong>本带他收单</strong></li>
<li><strong>收单代理</strong></li>
<li><strong>冲正交易</strong></li>
</ul>
<p>即一笔交易再终端已经置为成功标志，但是发送到主机的账务交易包没有得到响应，即终端交易超时。所以不确定该笔交易是否在主机端也成功完成吗，为了确保用户的利益，终端重新向主机发送请求，请求取消该笔交易的流水，如果主机端已经交易成功，则回滚交易，否则不处理，然后将处理结果返回给终端。</p>
<ul>
<li><strong>代付</strong></li>
</ul>
<p>指各商业银行利用自身的结算便利，接收客户的委托代为办理指定款项的收付事宜的业务。</p>
<ul>
<li><strong>代扣</strong></li>
</ul>
<p>用户和商户签订过一些代为扣款的协议后，系统会根据协议按时从客户签订协议的账户中扣除协定的金额，明细备注中就显示为&quot;代扣&quot;。</p>
<ul>
<li><strong>担保交易</strong></li>
<li><strong>借记卡快捷</strong></li>
<li><strong>信用卡快捷</strong></li>
<li><strong>借记卡一键支付</strong></li>
<li><strong>快捷支付</strong></li>
</ul>
<p>指用户购买商品时，不需开通网银，只需提供银行卡号、户名、手机号等信息，银行验证手机号正确性后，第三方支付机构发送手机动态口令到用户手机上，用户输入正确的手机动态口令，即可完成支付。</p>
<ul>
<li><strong>网关支付</strong></li>
</ul>
<p>是银行金融网络系统和互联网网络之间的接口，是由银行操作的将Innernet上传输的数据转换为金融机构内部数据的一组服务器设备，或由指派的第三方处理商家支付信息和顾客的支付指令。</p>
<ul>
<li><strong>认证支付</strong></li>
</ul>
<p>是由连连支付为互联网金融行业打造的一款支持实名认证的新型支付产品。相比以往的网络支付方式，认证支付能够确保互联网金融行业的高安全性要求，实现了投资人与持卡人的身份的识别，确保了交易安全。</p>
<ul>
<li><strong>小额免密支付</strong></li>
<li><strong>近场支付</strong></li>
<li><strong>数字电视支付</strong></li>
<li><strong>移动电话支付</strong></li>
<li><strong>银行呼叫中心支付</strong></li>
<li><strong>银行账户支付</strong></li>
<li><strong>远程支付</strong></li>
<li><strong>短信支付</strong></li>
</ul>
<h2>5.卡类型</h2>
<ul>
<li><strong>预付卡</strong></li>
<li><strong>借记卡</strong></li>
<li><strong>贷记卡</strong></li>
<li><strong>伪卡</strong></li>
<li><strong>准贷记卡</strong></li>
</ul>
<p>指银行发行的，持卡人按要求交存一定金额的备用金，当备用金账户余额不足支付时，可在规定的信用额度内透支的准贷记卡。</p>
<h2>6.业务名词</h2>
<h3>6.1 清结算</h3>
<ul>
<li><strong>总账</strong></li>
</ul>
<p>也称总分类账。是根据总分类科目开设账户，用来登记全部经济业务，进行总分类核算，提供总括核算资料的分类账簿。总分类账所提供的核算字段里奥，是编制会计报表的主要依据，任何单位都必须设置总分类账。</p>
<ul>
<li><strong>资金归集</strong></li>
</ul>
<p>是指将集团公司中所有下属公司指定账户上的资金归集到总公司指定的账户的服务，也称资金清扫。</p>
<ul>
<li><strong>账务处理</strong></li>
</ul>
<p>指从审计原始凭证、编制记账凭证开始，通过记账、对账、结账等一系列会计处理，到编制出会计报表的过程。</p>
<ul>
<li><strong>轧差</strong></li>
</ul>
<p>是指利用抵消、合同更新等法律制度，最终取得一方对另一方的一个数额的净债券或净债务，如市场交易者之间，可能互有内容相同，方向相反的多笔交易，在结算或结束交易时，可以将各方债权在相等数额内抵消、仅支付余额。</p>
<ul>
<li><strong>实时清分结算</strong></li>
</ul>
<p>清分是清算的数据准备阶段，主要是将当日的全部网络交易数据按照个成员行之间本带他、他带本、贷记、借记、笔数、金额、轧差净额等进行汇总、整理、分类。结算是指吧某一时期内的所有手指情况进行总结、核算。</p>
<ul>
<li><strong>清分</strong></li>
</ul>
<p>是清算的数据准备阶段, 主要是将当日的全部网络交易数据按照各成员行之间本代他、他代本、贷记、借记、笔数、金额、轧差净额等进行汇总、整理、分类。是指对交易记录汇总分类并计算出相互结算金额的过程。</p>
<ul>
<li><strong>明细账</strong></li>
</ul>
<p>按明细分类账户登记的账簿叫做明细分类账，简称”明细账“。明细账也称明细分类账，是根据总账科目所属的明细科目设置的，用于分类等级某一类经济业务事项，提供有关明细核算资料。</p>
<ul>
<li><strong>结算</strong></li>
<li><strong>分账</strong></li>
</ul>
<p>业务发生主体与业务关系方之间的相关利益和支出的划分分账，一般指的是媒体分账合作的一种营销模式。</p>
<ul>
<li><strong>分单</strong></li>
</ul>
<p>是指同一张银行卡在同一家商户同一终端购买同一商品(或者服务)而发生连续两次(含)以上交易的支付行为。</p>
<ul>
<li><strong>对账</strong></li>
</ul>
<p>是对前一个清算周期的交易信息进行核对，以确认交易信息的一致性和正确性的过程。</p>
<ul>
<li><strong>对账文件</strong></li>
</ul>
<p>确认交易信息一致性和正确性所用到的文件。</p>
<ul>
<li><strong>差错</strong></li>
</ul>
<p>是指由于机具、通信线路、系统处理、终端操作及其他原因引起，需要进行相应的账务调整的交易。</p>
<ul>
<li><strong>差错管理</strong></li>
</ul>
<p>是在数字通信中利用编码方法对传输过程中产生的差错进行管理，以提高数字消息传输的准确性。</p>
<ul>
<li><strong>调单</strong></li>
</ul>
<p>指的是调取交易签购单及凭证，确认交易真实性。一般由银联、发卡行或收单机构发起，服务商也可以进行发起。</p>
<ul>
<li><strong>掉单</strong></li>
</ul>
<p>由于网络、系统等不确定因素的影响，支付服务方未把支付结果信息返回给下单发起方。</p>
<ul>
<li><strong>撤单</strong></li>
</ul>
<p>在下单成功后，对于未支付的电子支付订单进行撤销的操作。</p>
<ul>
<li><strong>未达账(项)</strong></li>
<li><strong>账务处理</strong></li>
</ul>
<h3>6.2 安全性</h3>
<ul>
<li><strong>机密性</strong></li>
<li><strong>加密</strong></li>
<li><strong>解密</strong></li>
<li><strong>鉴权</strong></li>
<li><strong>密文</strong></li>
</ul>
<p>加密运算的结果。</p>
<ul>
<li><strong>密钥加密密钥</strong></li>
</ul>
<p>POS终端工作时对工作密钥进行加密的密钥，由银行人员设置并保持在本系统硬件中，只能够使用，不能够读取，该密钥必须与加密算法放在同一加密芯片里。</p>
<ul>
<li><strong>明文</strong></li>
</ul>
<p>未被加密的信息。</p>
<ul>
<li><strong>数字签名</strong></li>
<li><strong>数字证书</strong></li>
<li><strong>双重身份认证</strong></li>
</ul>
<h3>6.3 交易</h3>
<ul>
<li><strong>预授权</strong></li>
</ul>
<p>预授权指特约商户通过POS或其他方式，就持卡人预支付金额向发卡行索取付款承诺的过程。</p>
<ul>
<li><strong>预授权撤销</strong></li>
</ul>
<p>预授权撤销指特约商户由于各种原因通过POS或其他方式通知发卡行取消付款承诺的过程。</p>
<ul>
<li><strong>预授权完成</strong></li>
</ul>
<p>预授权完成指持卡人对已取得预授权的交易，在预授权金额或超出预授权金额一定比例的范围内，做支付结算。</p>
<ul>
<li><strong>预授权完成撤销</strong></li>
</ul>
<p>预授权完成撤销指特约商户由于各种的原因对持卡人已经完成的预授权完成交易，主动发起的预授权完成交易的取消。</p>
<ul>
<li><strong>支付网关</strong></li>
</ul>
<p>支付服务提供方用于处理支付指令的系统。</p>
<ul>
<li><strong>异常交易</strong></li>
<li><strong>信用卡拒付</strong></li>
<li><strong>拒付</strong></li>
</ul>
<p>付款方通过信用类支付方式付款给收款方后，由于某种原因拒绝支付货款的行为。（黑卡、盗卡、恶意支付等）</p>
<ul>
<li><strong>消费</strong></li>
<li><strong>下单</strong></li>
<li><strong>无卡支付</strong></li>
<li><strong>外收</strong></li>
</ul>
<p>是指在发生一笔交易时，所缴纳的手续费从这笔金额外收取，区别于内扣。</p>
<ul>
<li><strong>内扣</strong></li>
</ul>
<p>是指在发生一笔交易时，所缴纳的手续费从这笔金额内扣除，区别于外收。</p>
<ul>
<li><strong>退货</strong></li>
</ul>
<p>指商户应持卡人要求或主动将商品收回或服务取消，通过联机POS 终端等受理机具或者手工方式，将已扣款项通过收单银行退还给持卡人原扣款的过程。</p>
<ul>
<li><strong>退款</strong></li>
</ul>
<p>针对原交易进行的，将全部或部分支付款项退回到付款方账户的操作。</p>
<ul>
<li><strong>套现</strong></li>
</ul>
<p>套取现金的简称，一般是指用违法或虚假的手段交换取得现金利益。 多用于信用卡套现、公积金套现、证券套现等。</p>
<ul>
<li><strong>实时打款</strong></li>
</ul>
<p>指在交易过程中将款项交付给交易对方。</p>
<ul>
<li><strong>担保支付</strong></li>
</ul>
<h3>6.4 参与方</h3>
<ul>
<li><strong>支付服务方</strong></li>
</ul>
<p>在支付交易中提供资金收、付服务的银行和专业化支付服务提供方。</p>
<ul>
<li><strong>持卡人</strong></li>
</ul>
<p>卡的合法持有者，即与卡对应的银行账户相联系的客户。</p>
<ul>
<li><strong>付款方</strong></li>
</ul>
<p>在支付交易中支付资金的一方。</p>
<ul>
<li><strong>收款方</strong></li>
</ul>
<p>在支付交易中接收资金的一方。</p>
<ul>
<li><strong>收单行</strong></li>
</ul>
<p>指跨行交易中兑付现金或与商户签约进行跨行交易资金结算，并且直接或间接地使交易达成转接的银行。</p>
<ul>
<li><strong>收单机构</strong></li>
</ul>
<p>与商户签有协议或为持卡人提供服务，直接或间接凭交易单据(包括电子单据或纸质单据)参加交换的清算会员单位。</p>
<ul>
<li><strong>收单非焦点业务</strong></li>
</ul>
<p>收单非焦点业务包罗但不限于商户拓展与办事、终端布放与维护及生意业务接入等。</p>
<ul>
<li><strong>收单代理</strong></li>
</ul>
<p>具有资质的第三方支付机构通过渠道代理方式拓展商户。通俗的讲，就是通过与代理商签约，将POS机使用的商户拓展、资格审查等权力下放。</p>
<ul>
<li><strong>发卡行</strong></li>
</ul>
<p>发行银行卡，维护与卡关联的账户，并与持卡人在这两方面具有协议关系的机构。</p>
<ul>
<li><strong>电子支付</strong></li>
</ul>
<p>单位、个人直接或授权他人通过电子终端发出支付指令，实现货币支付与资金转移的行为。</p>
<ul>
<li><strong>电子支付终端</strong></li>
</ul>
<p>用户可用以发起电子支付指令的计算机、电话、销售点终端、自动柜员机、移动通讯工具或其他电子设备。</p>
<ul>
<li><strong>电子支付渠道</strong></li>
</ul>
<p>支付服务提供方为用户提供的完成电子支付的交易通道，如互联网、WAP、呼叫中心等。</p>
<ul>
<li><strong>电子支付平台</strong></li>
</ul>
<p>实现电子支付的业务处理系统。</p>
<ul>
<li><strong>电子支付结算</strong></li>
</ul>
<p>支付服务提供方对交易记录进行汇总、计算以及资金划转的全过程。</p>
<ul>
<li><strong>电子支付接口</strong></li>
</ul>
<p>基于约定的业务规则，用于电子支付数据交换的规范和技术实现。</p>
<ul>
<li><strong>电子支付交易监控</strong></li>
</ul>
<p>支付服务提供方在电子支付过程中，对交易行为进行监控。</p>
<ul>
<li><strong>电子支付安全评估</strong></li>
</ul>
<p>开展电子支付业务过程中，对支付服务提供方的安全策略、内控制度、风险管理、系统安全、用户保护等方面进行的安全测试和管控能力的考察与评价。</p>
<ul>
<li><strong>电子支付风险评估</strong></li>
</ul>
<p>对电子支付所面临的威胁、存在的弱点、造成的影响以及三者综合作用所带来风险的可能性评估。</p>
<ul>
<li><strong>电子支付对账</strong></li>
</ul>
<p>对前一个结算周期的交易信息进行核对，以确认交易信息的一致性和正确性的过程。</p>
<ul>
<li><strong>电子支付订单</strong></li>
</ul>
<p>包含订单编号、订单金额等支付信息的电子数据。</p>
<h2>9.参考链接</h2>
<ul>
<li><a href="http://www.gov.cn/zhengce/zhengceku/2021-01/23/content_5582141.htm" target="_blank" rel="noopener noreferrer">中国人民银行令〔2021〕第1号(非银行支付机构客户备付金存管办法)</a></li>
</ul>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="支付"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2021-12-01T18:26:19.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">Java对象头和锁的升级过程</title>
    <id>https://blog.ccoder.cc/posts/2022/Java-object-header-and-lock-upgrade.html</id>
    <link href="https://blog.ccoder.cc/posts/2022/Java-object-header-and-lock-upgrade.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>[TOC]</p>
<p>hello，大家好，我是聪聪。</p>
<hr>
<p>今天意外看到Java中有一个查看Java对象头的工具类<code>JOL</code>，正好可以通过Java对象头中所存储的信息来回顾一次锁的升级过程。</p>
<h3>1.JOL(Java Object Layout)</h3>
<blockquote>
<p>（Java对象布局）是分析JVM中对象布局方案的微型工具箱。这些工具大量使用不安全、JVMTI和可服务性代理（SA）来解码实际的对象布局、足迹和引用。这使得JOL比依赖堆转储、规范假设等的其他工具更精确。</p>
</blockquote>
<p>可以查看GitHub仓库:<a href="https://github.com/openjdk/jol" target="_blank" rel="noopener noreferrer">https://github.com/openjdk/jol</a>
相关依赖：</p>]]></summary>
    <content type="html"><![CDATA[<p>[TOC]</p>
<p>hello，大家好，我是聪聪。</p>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="Java"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2022-07-28T14:38:57.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">《领域驱动设计》之软件复杂度</title>
    <id>https://blog.ccoder.cc/posts/2022/ddd-software-complexty.html</id>
    <link href="https://blog.ccoder.cc/posts/2022/ddd-software-complexty.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>hello，大家好，我是聪聪。</p>
<hr>
<p>最近闲暇时间看了下张逸的《领域驱动设计》，书中对于软件复杂度包含的一些内容，让我有些同感。目前接触的一些系统中都会有一些<code>技术债</code>、<code>坏味道</code>在其中。</p>
<p>那么就在这里结合自身现有的一些系统设计，做一个随笔记录。</p>
<h3>1.复杂系统</h3>
<p>什么是复杂的系统呢？</p>
<blockquote>
<p>由大量相互作用的部分组成的系统。与整个系统比起来，这些组成部分相对简单，没有中央控制，组成部分之间没有全局性通信，并且组成部分的相互作用导致了复杂行为。</p>
</blockquote>]]></summary>
    <content type="html"><![CDATA[<p>hello，大家好，我是聪聪。</p>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="DDD"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2022-08-08T11:13:36.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">Go语言基础-数组</title>
    <id>https://blog.ccoder.cc/posts/2022/go-array.html</id>
    <link href="https://blog.ccoder.cc/posts/2022/go-array.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>hello，大家好，我是聪聪。</p>
<hr>
<h2>1.数组定义</h2>
<p>数组是同一类型元素的集合。在go中数组从声明时便已确认，使用时可以修改其成员，但是数组大小不可变化。</p>
<blockquote>
<p>[n]T 用来定义数据</p>
<ul>
<li>n 数组元素个数</li>
<li>T 数组元素的数据类型</li>
</ul>
<p>var a [10]int
定义一个长度为10，元素类型为int的数组 a</p>
</blockquote>
<h2>2.数组初始化</h2>
<h3>2.1 使用初始化列表来完成数组初始化</h3>
<blockquote>
<p>var 数组变量名 [元素数量,数据长度] 数据类型
var a [3]int</p>
</blockquote>]]></summary>
    <content type="html"><![CDATA[<p>hello，大家好，我是聪聪。</p>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="Go"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2022-09-21T14:10:02.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">viper读取配置文件</title>
    <id>https://blog.ccoder.cc/posts/2022/go-viper.html</id>
    <link href="https://blog.ccoder.cc/posts/2022/go-viper.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>hello，大家好，我是聪聪。</p>
<hr>
<h2>1. 介绍</h2>
<p><a href="https://github.com/spf13/viper" target="_blank" rel="noopener noreferrer">Viper</a>是适用于Go应用程序的完整配置解决方案。它被设计用于在应用程序中工作，并且可以处理所有类型的配置需求和格式。它支持以下特性：</p>
<ul>
<li>设置默认值</li>
<li>从<code>JSON</code>、<code>TOML</code>、<code>YAML</code>、<code>HCL</code>、<code>envfile</code>和<code>Java properties</code>格式的配置文件读取配置信息</li>
<li>实时监控和重新读取配置文件（可选）</li>
<li>从环境变量中读取</li>
<li>从远程配置系统（etcd或Consul）读取并监控配置变化</li>
<li>从命令行参数读取配置</li>
<li>从buffer读取配置</li>
<li>显式配置值</li>
</ul>]]></summary>
    <content type="html"><![CDATA[<p>hello，大家好，我是聪聪。</p>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="Go"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2022-09-23T16:29:21.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">货币代码</title>
    <id>https://blog.ccoder.cc/posts/2022/huo-bi-dai-ma.html</id>
    <link href="https://blog.ccoder.cc/posts/2022/huo-bi-dai-ma.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>ALL	8	阿尔巴尼列克 - Albania Lek	阿尔巴尼
DZD	12	阿尔及利亚第纳尔 - Algerian Dinar	阿尔及利亚
ARS	32	阿根廷比索 - Argentina Peso	阿根廷
AUD	36	澳元 - Australia Dollar	澳大利亚
BSD	44	巴哈马元 - Bahamian Dollar	巴哈马元
BHD	48	巴林第纳尔 - Bahrain Dinar	巴林
BDT	50	孟加拉国塔卡 - Bangladesh Taka	孟加拉国
AMD	51	亚美尼亚德拉姆 - Armenia Dram	亚美尼亚
BBD	52	巴巴多斯元 - Barbados Dollar	巴巴多斯
BMD	60	百慕大元 - Bermudian Dollar	百慕大
BTN	64	不丹努扎姆 - Bhutanese Ngultrum	不丹
BOB	68	玻利维亚诺 - Bolivian Boliviano	玻利维亚
BWP	72	博茨瓦纳普拉 - Botswana Pula	博茨瓦纳
BZD	84	伯利兹元 - Belize Dollar	伯利兹
SBD	90	所罗门群岛元 - Solomon Islands Dollar	所罗门群岛
BND	96	文莱元 - Brunei Dollar	文莱
MMK	104	缅甸元 - Myanmar Kyat	缅甸
BIF	108	布隆迪法郎 - Burundi Franc	布隆迪
KHR	116	柬埔寨瑞尔 - Cambodian Riel	柬埔寨
CAD	124	加元 - Canadian Dollar	加拿大
CVE	132	佛得角埃斯库多 - Cape Verde Escudo	佛得角
KYD	136	开曼群岛元 - Cayman Islands Dollar	开曼群岛
LKR	144	斯里兰卡卢比 - Sri Lankan Rupee	斯里兰卡
CLP	152	智利比索 - Chilean Peso	智利
CNY	156	人民币 - Chinese Yuan	中国
COP	170	哥伦比亚比索 - Colombia Peso	哥伦比亚
KMF	174	科摩罗法郎 - Comorian franc	科摩罗
CRC	188	哥斯达黎加科朗 - Costa Rica Colon	哥斯达黎加
HRK	191	克罗地亚库纳 - Croatian Kuna	克罗地亚
CUP	192	古巴比索 - Cuban Peso	古巴
CYP	196	塞普路斯镑 - Cyprus Pound	塞普路斯
CZK	203	捷克克朗 - Czech Republic Koruna	捷克
DKK	208	丹麦克朗 - Danish Krone	丹麦
DOP	214	多米尼加比索 - Dominican Peso	多米尼加
ECS	218	厄瓜多尔苏克雷 - Ecuadorian Sucre	厄瓜多尔
SVC	222	萨尔瓦多科朗 - Salvadoran Colon	萨尔瓦多
ETB	230	埃塞俄比亚比尔 - Ethiopian Birr	埃塞俄比亚
ERN	232	厄立特里亚纳克法 - Eritrean Nakfa	厄立特里亚
FKP	238	福克兰群岛镑 - Falkland Islands Pound	福克兰群岛
FJD	242	斐济元 - Fiji Dollar	斐济
FRF	250	法国法郎 - French Franc	法国
DJF	262	吉布提法郎 - Djiboutian Franc	吉布提
GMD	270	冈比亚达拉西 - Gambian Dalasi	冈比亚
DEM	280	德国马克 - Deutsche Mark	德国
GIP	292	直布罗陀镑 - Gibraltar Pound	直布罗陀
GTQ	320	危地马拉格查尔 - Guatemalan Quetzal	危地马拉
GNF	324	几内亚法郎 - Guinean Franc	几内亚
GYD	328	圭亚那元 - Guyanese Dollar	圭亚那
HTG	332	海地古德 - Haitian Gourde	海地
HNL	340	洪都拉斯伦皮拉 - Honduran Lempira	洪都拉斯
HKD	344	港币 - Hong Kong Dollar	香港
HUF	348	匈牙利福林 - Hungarian Forint	匈牙利
ISK	352	冰岛克郎 - Icelandic Krona	冰岛
INR	356	印度卢比 - Indian Rupee	印度
IDR	360	印度尼西亚卢比 - Indonesian Rupiah	印度尼西亚
IRR	364	伊朗里亚尔 - Iranian Rial	伊朗
IQD	368	伊拉克第纳尔 - Iraqi Dinar	伊拉克
IEP	372	爱尔兰镑 - Irish Pound	爱尔兰
ILS	376	以色列新谢克尔 - Israeli New Shekel	以色列
ITL	380	意大利里拉 - Italian Lira	意大利
JMD	388	牙买加元 - Jamaican Dollar	牙买加
JPY	392	日元 - Japanese Yen	日本
KZT	398	哈萨克斯坦坚戈 - Kazakstani Tenge	哈萨克斯坦
JOD	400	约旦第纳尔 - Jordanian Dinar	约旦
KES	404	肯尼亚先令 - Kenyan Shilling	肯尼亚
KPW	408	朝鲜元 - North Korean Won	朝鲜
KRW	410	韩元 - South Korean Won	韩国
KWD	414	科威特第纳尔 - Kuwaiti Dinar	科威特
KGS	417	吉尔吉斯斯坦索姆 - Kyrgyzstani Som	吉尔吉斯斯坦
LAK	418	老挝基普 - Lao kip	老挝
LBP	422	黎巴嫩镑 - Lebanese Pound	黎巴嫩
LSL	426	莱索托洛蒂 - Lesotho Loti	莱索托
LVL	428	拉脱维亚拉特 - Latvian Lats	拉脱维亚
LRD	430	利比里亚元 - Liberian dollar	利比里
LYD	434	利比亚第纳尔 - Libyan Dinar	利比亚
LTL	440	立陶宛立特 - Lithuanian Litas	立陶宛
MOP	446	澳门元 - Macau Pataca	澳门
MWK	454	马拉维克瓦查 - Malawian Kwacha	马拉维
MYR	458	林吉特 - Malaysian Ringgit	马来西亚
MVR	462	马尔代夫拉菲亚 - Maldives Rufiyaa	马尔代夫
MRO	478	毛里塔尼亚乌吉亚 - Mauritania Ouguiya	毛里塔尼亚
MUR	480	毛里求斯卢比 - Mauritian Rupee	毛里求斯
MXN	484	墨西哥比索 - Mexican Peso	墨西哥
MNT	496	蒙古图格里克 - Mongolian Tugrik	蒙古
MDL	498	摩尔多瓦列伊 - Moldovan Leu	摩尔多瓦
MAD	504	摩洛哥迪拉姆 - Moroccan Dirham	摩洛哥
OMR	512	阿曼里亚尔 - Omani Rial	阿曼
NAD	516	纳米比亚元 - Namibian Dollar	纳米比亚
NPR	524	尼泊尔卢比 - Nepalese Rupee	尼泊尔
ANG	532	荷兰盾 - Dutch Guilder	荷兰
AWG	533	阿鲁巴弗罗林 - Aruba Florin	阿鲁巴
VUV	548	瓦努阿图瓦图 - Vanuatu Vatu	瓦努阿图
NZD	554	新西兰元 - New Zealand Dollar	新西兰
NIO	558	尼加拉瓜新科多巴 - Nicaraguan Cordoba Oro	尼加拉瓜
NGN	566	尼日利亚奈拉 - Nigerian Naira	尼日利亚
NOK	578	挪威克朗 - Norwegian Krone	挪威
PKR	586	巴基斯坦卢比 - Pakistan Rupee	巴基斯坦
PAB	590	巴拿马巴波亚 - Panamanian Balboa	巴拿马
PGK	598	巴布亚新几内亚基那 - Papua New Guinea Kina	巴布亚新几内亚
PYG	600	巴拉圭瓜拉尼 - Paraguayan Guarani	巴拉圭
PEN	604	秘鲁新索尔 - Peruvian Nuevo Sol	秘鲁
PHP	608	菲律宾比索 - Philippine Peso	菲律宾
QAR	634	卡塔尔里亚尔 - Qatari Riyal	卡塔尔
RUB	643	俄罗斯卢布 - Russian Ruble	俄罗斯
RWF	646	卢旺达法郎 - Rwandan Franc	卢旺达
SHP	654	圣赫勒拿镑 - Saint Helena Pound	圣赫勒拿(英属)
STD	678	圣多美多布拉 - Sao Tome Dobra	圣多美和普林西比
SAR	682	沙特里亚尔 - Saudi Arabian Riyal	沙特阿拉伯
SCR	690	塞舌尔卢比 - Seychelles Rupee	塞舌尔
SLL	694	塞拉利昂利昂 - Sierra Leonean Leone	塞拉利昂
SGD	702	新加坡元 - Singapore Dollar	新加坡
VND	704	越南盾 - Viet Nam Dong	越南
SIT	705	斯洛文尼亚托拉尔 - Slovenian Tolar	斯洛文尼亚
SOS	706	索马里先令 - Somali Shilling	索马里
ZAR	710	南非兰特 - South African Rand	南非
ZWL	716	津巴布韦元 - Zimbabwean Dollar	津巴布韦
SZL	748	斯威士兰里兰吉尼 - Swazi Lilangeni	斯威士兰
SEK	752	瑞典克朗 - Swedish Krona	瑞典
CHF	756	瑞士法郎 - Swiss Franc	瑞士
SYP	760	叙利亚镑 - Syrian Pound	叙利亚
THB	764	泰铢 - Thai Baht	泰国
TOP	776	汤加潘加 - Tongan Pa'Anga	汤加
TTD	780	特立尼达多巴哥元 - Trinidad and Tobago Dollar	特立尼达多巴哥
AED	784	阿联酋迪拉姆 - United Arab Emirates Dirham	阿联酋
TND	788	突尼斯第纳尔 - Tunisian Dinar	突尼斯
UGX	800	乌干达先令 - Ugandan Shilling	乌干达
MKD	807	马其顿代纳尔 - Macedonian Denar	马其顿
EGP	818	埃及镑 - Egyptian Pound	埃及
GBP	826	英镑 - British Pound	英国
TZS	834	坦桑尼亚先令 - Tanzanian Shilling	坦桑尼亚
USD	840	美元 - United States Dollar	美国
UYU	858	乌拉圭比索 - Uruguayan Peso	乌拉圭
UZS	860	乌兹别克斯坦苏姆 - Uzbekistani Som	乌兹别克斯坦
WST	882	萨摩亚塔拉 - Samoa Tala	萨摩亚
YER	886	也门里亚尔 - Yemeni Rial	也门
TWD	901	新台币 - New Taiwan Dollar	台湾
TMT	934	土库曼斯坦马纳特 - Turkmenistan Manat	土库曼斯坦
GHS	936	加纳塞地 - Ghanaian Cedi	加纳
VEF	937	委内瑞拉玻利瓦尔 - Venezuelan Bolivar Fuerte	委内瑞拉
SDG	938	苏丹镑 - Sudanese Pound	苏丹
RSD	941	塞尔维亚第纳尔 - Serbian Dinar	塞尔维亚
MZN	943	莫桑比克新梅蒂卡尔 - New Mozambican Metical	莫桑比克
AZN	944	阿塞拜疆马纳特 - Azerbaijan Manat	阿塞拜疆
RON	946	罗马尼亚列伊 - Romanian Leu	罗马尼亚
TRY	949	土耳其里拉 - Turkish Lira	土耳其
XAF	950	中非法郎 - Central African CFA Franc	中非经济共同体
XCD	951	东加勒比元 - East Caribbean Dollar	加勒比海(英属)
XOF	952	西非法郎 - West African CFA	非洲金融共同体
XPF	953	太平洋法郎 - French Pacific Franc	三个太平洋辖区(法属)
XAU	959	金价盎司 - Ounces of Gold	贵金属
XDR	960	IMF特别提款权 - IMF Special Drawing Rights	国际货币基金组织
XAG	961	银价盎司 - Ounces of Silver	贵金属
XPT	962	珀价盎司 - Ounces of Platinum	贵金属
XPD	964	钯价盎司 - Ounces of Palladium	贵金属
ZMW	967	赞比亚克瓦查 - Zambian Kwacha	赞比亚
SRD	968	苏里南元 - Suriname Dollar	苏里南元
MGA	969	马达加斯加阿里亚里 - Malagasy Ariary	马达加斯加
AFN	971	阿富汗尼 - Afghan Afghani	阿富汗
TJS	972	塔吉克斯坦索莫尼 - Tajikistan Somoni	塔吉克斯坦
AOA	973	安哥拉宽扎 - Angola Kwanza	安哥拉
BYR	974	白俄罗斯卢布 - Belarusian Ruble	白俄罗斯
BGN	975	保加利亚列弗 - Bulgaria Lev	保加利亚
CDF	976	刚果法郎 - Congolese Franc	刚果
BAM	977	波黑可兑换马克 - Bosnia Convertible Mark	波黑
EUR	978	欧元 - Euro	欧盟
MXV	979	墨西哥(资金) - Mexican Unidad De Inversion	墨西哥
UAH	980	乌克兰格里夫纳 - Ukrainian Hryvnia	乌克兰
GEL	981	格鲁吉亚拉里 - Georgian Lari	格鲁吉亚
PLN	985	波兰兹罗提 - Polish Zloty	波兰
BRL	986	巴西雷亚尔 - Brazilian Real	巴西
CLF	990	智利比索(基金) - Chilean Unidad de Fomento	智利
BTC	
比特币 - BitCoin	中本聪
CNH	
中国离岸人民币 - Chinese Offshore Renminbi	中国
XCP	
铜价盎司 - Ounces of Copper	贵金属</p>]]></summary>
    <content type="html"><![CDATA[<p>ALL	8	阿尔巴尼列克 - Albania Lek	阿尔巴尼
DZD	12	阿尔及利亚第纳尔 - Algerian Dinar	阿尔及利亚
ARS	32	阿根廷比索 - Argentina Peso	阿根廷
AUD	36	澳元 - Australia Dollar	澳大利亚
BSD	44	巴哈马元 - Bahamian Dollar	巴哈马元
BHD	48	巴林第纳尔 - Bahrain Dinar	巴林
BDT	50	孟加拉国塔卡 - Bangladesh Taka	孟加拉国
AMD	51	亚美尼亚德拉姆 - Armenia Dram	亚美尼亚
BBD	52	巴巴多斯元 - Barbados Dollar	巴巴多斯
BMD	60	百慕大元 - Bermudian Dollar	百慕大
BTN	64	不丹努扎姆 - Bhutanese Ngultrum	不丹
BOB	68	玻利维亚诺 - Bolivian Boliviano	玻利维亚
BWP	72	博茨瓦纳普拉 - Botswana Pula	博茨瓦纳
BZD	84	伯利兹元 - Belize Dollar	伯利兹
SBD	90	所罗门群岛元 - Solomon Islands Dollar	所罗门群岛
BND	96	文莱元 - Brunei Dollar	文莱
MMK	104	缅甸元 - Myanmar Kyat	缅甸
BIF	108	布隆迪法郎 - Burundi Franc	布隆迪
KHR	116	柬埔寨瑞尔 - Cambodian Riel	柬埔寨
CAD	124	加元 - Canadian Dollar	加拿大
CVE	132	佛得角埃斯库多 - Cape Verde Escudo	佛得角
KYD	136	开曼群岛元 - Cayman Islands Dollar	开曼群岛
LKR	144	斯里兰卡卢比 - Sri Lankan Rupee	斯里兰卡
CLP	152	智利比索 - Chilean Peso	智利
CNY	156	人民币 - Chinese Yuan	中国
COP	170	哥伦比亚比索 - Colombia Peso	哥伦比亚
KMF	174	科摩罗法郎 - Comorian franc	科摩罗
CRC	188	哥斯达黎加科朗 - Costa Rica Colon	哥斯达黎加
HRK	191	克罗地亚库纳 - Croatian Kuna	克罗地亚
CUP	192	古巴比索 - Cuban Peso	古巴
CYP	196	塞普路斯镑 - Cyprus Pound	塞普路斯
CZK	203	捷克克朗 - Czech Republic Koruna	捷克
DKK	208	丹麦克朗 - Danish Krone	丹麦
DOP	214	多米尼加比索 - Dominican Peso	多米尼加
ECS	218	厄瓜多尔苏克雷 - Ecuadorian Sucre	厄瓜多尔
SVC	222	萨尔瓦多科朗 - Salvadoran Colon	萨尔瓦多
ETB	230	埃塞俄比亚比尔 - Ethiopian Birr	埃塞俄比亚
ERN	232	厄立特里亚纳克法 - Eritrean Nakfa	厄立特里亚
FKP	238	福克兰群岛镑 - Falkland Islands Pound	福克兰群岛
FJD	242	斐济元 - Fiji Dollar	斐济
FRF	250	法国法郎 - French Franc	法国
DJF	262	吉布提法郎 - Djiboutian Franc	吉布提
GMD	270	冈比亚达拉西 - Gambian Dalasi	冈比亚
DEM	280	德国马克 - Deutsche Mark	德国
GIP	292	直布罗陀镑 - Gibraltar Pound	直布罗陀
GTQ	320	危地马拉格查尔 - Guatemalan Quetzal	危地马拉
GNF	324	几内亚法郎 - Guinean Franc	几内亚
GYD	328	圭亚那元 - Guyanese Dollar	圭亚那
HTG	332	海地古德 - Haitian Gourde	海地
HNL	340	洪都拉斯伦皮拉 - Honduran Lempira	洪都拉斯
HKD	344	港币 - Hong Kong Dollar	香港
HUF	348	匈牙利福林 - Hungarian Forint	匈牙利
ISK	352	冰岛克郎 - Icelandic Krona	冰岛
INR	356	印度卢比 - Indian Rupee	印度
IDR	360	印度尼西亚卢比 - Indonesian Rupiah	印度尼西亚
IRR	364	伊朗里亚尔 - Iranian Rial	伊朗
IQD	368	伊拉克第纳尔 - Iraqi Dinar	伊拉克
IEP	372	爱尔兰镑 - Irish Pound	爱尔兰
ILS	376	以色列新谢克尔 - Israeli New Shekel	以色列
ITL	380	意大利里拉 - Italian Lira	意大利
JMD	388	牙买加元 - Jamaican Dollar	牙买加
JPY	392	日元 - Japanese Yen	日本
KZT	398	哈萨克斯坦坚戈 - Kazakstani Tenge	哈萨克斯坦
JOD	400	约旦第纳尔 - Jordanian Dinar	约旦
KES	404	肯尼亚先令 - Kenyan Shilling	肯尼亚
KPW	408	朝鲜元 - North Korean Won	朝鲜
KRW	410	韩元 - South Korean Won	韩国
KWD	414	科威特第纳尔 - Kuwaiti Dinar	科威特
KGS	417	吉尔吉斯斯坦索姆 - Kyrgyzstani Som	吉尔吉斯斯坦
LAK	418	老挝基普 - Lao kip	老挝
LBP	422	黎巴嫩镑 - Lebanese Pound	黎巴嫩
LSL	426	莱索托洛蒂 - Lesotho Loti	莱索托
LVL	428	拉脱维亚拉特 - Latvian Lats	拉脱维亚
LRD	430	利比里亚元 - Liberian dollar	利比里
LYD	434	利比亚第纳尔 - Libyan Dinar	利比亚
LTL	440	立陶宛立特 - Lithuanian Litas	立陶宛
MOP	446	澳门元 - Macau Pataca	澳门
MWK	454	马拉维克瓦查 - Malawian Kwacha	马拉维
MYR	458	林吉特 - Malaysian Ringgit	马来西亚
MVR	462	马尔代夫拉菲亚 - Maldives Rufiyaa	马尔代夫
MRO	478	毛里塔尼亚乌吉亚 - Mauritania Ouguiya	毛里塔尼亚
MUR	480	毛里求斯卢比 - Mauritian Rupee	毛里求斯
MXN	484	墨西哥比索 - Mexican Peso	墨西哥
MNT	496	蒙古图格里克 - Mongolian Tugrik	蒙古
MDL	498	摩尔多瓦列伊 - Moldovan Leu	摩尔多瓦
MAD	504	摩洛哥迪拉姆 - Moroccan Dirham	摩洛哥
OMR	512	阿曼里亚尔 - Omani Rial	阿曼
NAD	516	纳米比亚元 - Namibian Dollar	纳米比亚
NPR	524	尼泊尔卢比 - Nepalese Rupee	尼泊尔
ANG	532	荷兰盾 - Dutch Guilder	荷兰
AWG	533	阿鲁巴弗罗林 - Aruba Florin	阿鲁巴
VUV	548	瓦努阿图瓦图 - Vanuatu Vatu	瓦努阿图
NZD	554	新西兰元 - New Zealand Dollar	新西兰
NIO	558	尼加拉瓜新科多巴 - Nicaraguan Cordoba Oro	尼加拉瓜
NGN	566	尼日利亚奈拉 - Nigerian Naira	尼日利亚
NOK	578	挪威克朗 - Norwegian Krone	挪威
PKR	586	巴基斯坦卢比 - Pakistan Rupee	巴基斯坦
PAB	590	巴拿马巴波亚 - Panamanian Balboa	巴拿马
PGK	598	巴布亚新几内亚基那 - Papua New Guinea Kina	巴布亚新几内亚
PYG	600	巴拉圭瓜拉尼 - Paraguayan Guarani	巴拉圭
PEN	604	秘鲁新索尔 - Peruvian Nuevo Sol	秘鲁
PHP	608	菲律宾比索 - Philippine Peso	菲律宾
QAR	634	卡塔尔里亚尔 - Qatari Riyal	卡塔尔
RUB	643	俄罗斯卢布 - Russian Ruble	俄罗斯
RWF	646	卢旺达法郎 - Rwandan Franc	卢旺达
SHP	654	圣赫勒拿镑 - Saint Helena Pound	圣赫勒拿(英属)
STD	678	圣多美多布拉 - Sao Tome Dobra	圣多美和普林西比
SAR	682	沙特里亚尔 - Saudi Arabian Riyal	沙特阿拉伯
SCR	690	塞舌尔卢比 - Seychelles Rupee	塞舌尔
SLL	694	塞拉利昂利昂 - Sierra Leonean Leone	塞拉利昂
SGD	702	新加坡元 - Singapore Dollar	新加坡
VND	704	越南盾 - Viet Nam Dong	越南
SIT	705	斯洛文尼亚托拉尔 - Slovenian Tolar	斯洛文尼亚
SOS	706	索马里先令 - Somali Shilling	索马里
ZAR	710	南非兰特 - South African Rand	南非
ZWL	716	津巴布韦元 - Zimbabwean Dollar	津巴布韦
SZL	748	斯威士兰里兰吉尼 - Swazi Lilangeni	斯威士兰
SEK	752	瑞典克朗 - Swedish Krona	瑞典
CHF	756	瑞士法郎 - Swiss Franc	瑞士
SYP	760	叙利亚镑 - Syrian Pound	叙利亚
THB	764	泰铢 - Thai Baht	泰国
TOP	776	汤加潘加 - Tongan Pa'Anga	汤加
TTD	780	特立尼达多巴哥元 - Trinidad and Tobago Dollar	特立尼达多巴哥
AED	784	阿联酋迪拉姆 - United Arab Emirates Dirham	阿联酋
TND	788	突尼斯第纳尔 - Tunisian Dinar	突尼斯
UGX	800	乌干达先令 - Ugandan Shilling	乌干达
MKD	807	马其顿代纳尔 - Macedonian Denar	马其顿
EGP	818	埃及镑 - Egyptian Pound	埃及
GBP	826	英镑 - British Pound	英国
TZS	834	坦桑尼亚先令 - Tanzanian Shilling	坦桑尼亚
USD	840	美元 - United States Dollar	美国
UYU	858	乌拉圭比索 - Uruguayan Peso	乌拉圭
UZS	860	乌兹别克斯坦苏姆 - Uzbekistani Som	乌兹别克斯坦
WST	882	萨摩亚塔拉 - Samoa Tala	萨摩亚
YER	886	也门里亚尔 - Yemeni Rial	也门
TWD	901	新台币 - New Taiwan Dollar	台湾
TMT	934	土库曼斯坦马纳特 - Turkmenistan Manat	土库曼斯坦
GHS	936	加纳塞地 - Ghanaian Cedi	加纳
VEF	937	委内瑞拉玻利瓦尔 - Venezuelan Bolivar Fuerte	委内瑞拉
SDG	938	苏丹镑 - Sudanese Pound	苏丹
RSD	941	塞尔维亚第纳尔 - Serbian Dinar	塞尔维亚
MZN	943	莫桑比克新梅蒂卡尔 - New Mozambican Metical	莫桑比克
AZN	944	阿塞拜疆马纳特 - Azerbaijan Manat	阿塞拜疆
RON	946	罗马尼亚列伊 - Romanian Leu	罗马尼亚
TRY	949	土耳其里拉 - Turkish Lira	土耳其
XAF	950	中非法郎 - Central African CFA Franc	中非经济共同体
XCD	951	东加勒比元 - East Caribbean Dollar	加勒比海(英属)
XOF	952	西非法郎 - West African CFA	非洲金融共同体
XPF	953	太平洋法郎 - French Pacific Franc	三个太平洋辖区(法属)
XAU	959	金价盎司 - Ounces of Gold	贵金属
XDR	960	IMF特别提款权 - IMF Special Drawing Rights	国际货币基金组织
XAG	961	银价盎司 - Ounces of Silver	贵金属
XPT	962	珀价盎司 - Ounces of Platinum	贵金属
XPD	964	钯价盎司 - Ounces of Palladium	贵金属
ZMW	967	赞比亚克瓦查 - Zambian Kwacha	赞比亚
SRD	968	苏里南元 - Suriname Dollar	苏里南元
MGA	969	马达加斯加阿里亚里 - Malagasy Ariary	马达加斯加
AFN	971	阿富汗尼 - Afghan Afghani	阿富汗
TJS	972	塔吉克斯坦索莫尼 - Tajikistan Somoni	塔吉克斯坦
AOA	973	安哥拉宽扎 - Angola Kwanza	安哥拉
BYR	974	白俄罗斯卢布 - Belarusian Ruble	白俄罗斯
BGN	975	保加利亚列弗 - Bulgaria Lev	保加利亚
CDF	976	刚果法郎 - Congolese Franc	刚果
BAM	977	波黑可兑换马克 - Bosnia Convertible Mark	波黑
EUR	978	欧元 - Euro	欧盟
MXV	979	墨西哥(资金) - Mexican Unidad De Inversion	墨西哥
UAH	980	乌克兰格里夫纳 - Ukrainian Hryvnia	乌克兰
GEL	981	格鲁吉亚拉里 - Georgian Lari	格鲁吉亚
PLN	985	波兰兹罗提 - Polish Zloty	波兰
BRL	986	巴西雷亚尔 - Brazilian Real	巴西
CLF	990	智利比索(基金) - Chilean Unidad de Fomento	智利
BTC	
比特币 - BitCoin	中本聪
CNH	
中国离岸人民币 - Chinese Offshore Renminbi	中国
XCP	
铜价盎司 - Ounces of Copper	贵金属</p>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="清算知识"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2022-02-11T18:24:22.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">利用SPI机制进行插件解耦</title>
    <id>https://blog.ccoder.cc/posts/2022/java-spi.html</id>
    <link href="https://blog.ccoder.cc/posts/2022/java-spi.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>[TOC]</p>
<p>hello，大家好，我是聪聪。</p>
<hr>
<p>最近在重构一款底层数据加解密中间件，里面有一些内容需要解耦：</p>
<ul>
<li>针对不同数据源处理单独，MySQL、MongoDB、ES数据源进行加解密处理。</li>
<li>可插拔扩展不同加解密算法。</li>
<li>兼容不同日志框架做数据脱敏，自定义客制化脱敏规则。</li>
</ul>
<p>在这里设想通过SPI机制，让接入业务方可进行插件客制化扩展。
中间件内提供业务通用AES加解密方法，同时提供接口业务方自行扩展其他加解密算法：RSA等。
那么就在这里总结一下SPI机制是什么。</p>]]></summary>
    <content type="html"><![CDATA[<p>[TOC]</p>
<p>hello，大家好，我是聪聪。</p>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="Java"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2022-08-16T15:07:09.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">京东京喜-武汉-高级Java工程师</title>
    <id>https://blog.ccoder.cc/posts/2022/jd-wuhan-jishumina-one.html</id>
    <link href="https://blog.ccoder.cc/posts/2022/jd-wuhan-jishumina-one.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<h3>RabbitMQ 多消费者时如何消息分配</h3>
<h3>RabbitMQ 消息最终一致性解决方案</h3>
<h3>RabbitMQ 延迟队列、消息延迟推送</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/haixiang/p/10966985.html" target="_blank" rel="noopener noreferrer">RabbitMQ延迟队列</a></li>
<li><a href="https://www.cnblogs.com/haixiang/p/10905189.html" target="_blank" rel="noopener noreferrer">RabbitMQ消费端限流、TTL、死信队列</a></li>
</ul>
</blockquote>]]></summary>
    <content type="html"><![CDATA[<h3>RabbitMQ 多消费者时如何消息分配</h3>
<h3>RabbitMQ 消息最终一致性解决方案</h3>
<h3>RabbitMQ 延迟队列、消息延迟推送</h3>
<blockquote>
<ul>
<li><a href="https://www.cnblogs.com/haixiang/p/10966985.html" target="_blank" rel="noopener noreferrer">RabbitMQ延迟队列</a></li>
<li><a href="https://www.cnblogs.com/haixiang/p/10905189.html" target="_blank" rel="noopener noreferrer">RabbitMQ消费端限流、TTL、死信队列</a></li>
</ul>
</blockquote>
<h3>Redis缓存雪崩、穿透、击穿区别和解决方案</h3>
<h3>接口调优</h3>
<blockquote>
<ul>
<li><a href="https://cloud.tencent.com/developer/article/1637579" target="_blank" rel="noopener noreferrer">接口性能调优方案</a></li>
</ul>
</blockquote>
<h3>Redis和MySQL数据一致性</h3>
<blockquote>
<ul>
<li><a href="https://www.its404.com/article/alionsss/107451485" target="_blank" rel="noopener noreferrer">分布式缓存一致性</a></li>
</ul>
</blockquote>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="面试"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2022-01-05T14:08:21.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
  <entry>
    <title type="text">MySQL-Explain总结</title>
    <id>https://blog.ccoder.cc/posts/2022/mysql-explain.html</id>
    <link href="https://blog.ccoder.cc/posts/2022/mysql-explain.html"/>
    <updated>2026-07-09T05:08:14.000Z</updated>
    <summary type="html"><![CDATA[<p>hello，大家好，我是聪聪。</p>
<hr>
<p>最近在梳理MySQL常用知识点，将已有知识点进行结构化、方便后续回稳固。</p>
<p>今天就来总结梳理一下常用的<code>explain</code>命令。</p>
<p><code>explian</code>命名是用来获取查询执行计划的信息，查询优化器是如何决定执行查询的主要方法。</p>
<h3>1. 如何使用</h3>
<p>使用非常简单，只需在查询语句<code>select</code>关键字前添加<code>explain</code>即可。MySQL会在该查询方法上进行标记，当执行查询时，标记会返回该执行计划中的每一步信息，而不是执行它，并且会返回多行信息，显示执行计划中的每一步和执行顺序。</p>]]></summary>
    <content type="html"><![CDATA[<p>hello，大家好，我是聪聪。</p>
]]></content>
    <author>
      <name>聪聪</name>
    </author>
    <category term="MySQL"/>
    <contributor>
      <name>聪聪</name>
    </contributor>
    <published>2022-08-11T10:40:11.000Z</published>
    <rights>Copyright by 聪聪</rights>
  </entry>
</feed>