<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>WhatAKitty Daily</title>
  
  <subtitle>A Programmer&#39;s Daily Record</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://xuqiang.me/"/>
  <updated>2020-06-29T18:39:00.742Z</updated>
  <id>https://xuqiang.me/</id>
  
  <author>
    <name>WhatAKitty</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Eureka内核逻辑解析</title>
    <link href="https://xuqiang.me/Eureka%E5%86%85%E6%A0%B8%E9%80%BB%E8%BE%91%E8%A7%A3%E6%9E%90.html"/>
    <id>https://xuqiang.me/Eureka内核逻辑解析.html</id>
    <published>2020-06-29T17:23:36.000Z</published>
    <updated>2020-06-29T18:39:00.742Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x6982;&#x89C8;"><a href="#&#x6982;&#x89C8;" class="headerlink" title="&#x6982;&#x89C8;"></a>&#x6982;&#x89C8;</h3><p><img src="https://static.xuqiang.me/public/images/161317.jpg" alt="Eureka&#x9AD8;&#x53EF;&#x7528;&#x67B6;&#x6784;"></p><p>&#x672C;&#x6587;&#x5206;&#x4EE5;&#x4E0B;&#x51E0;&#x70B9;&#xFF1A;</p><ol><li>Eureka&#x7684;&#x9AD8;&#x53EF;&#x7528;&#x5B9E;&#x73B0;<br>a. eureka&#x5BA2;&#x6237;&#x7AEF;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x901A;&#x8BAF;&#x673A;&#x5236;<br>b. eureka&#x670D;&#x52A1;&#x7AEF;&#x4E0E;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x8282;&#x70B9;&#x7684;&#x901A;&#x8BAF;<br>c. eureka&#x670D;&#x52A1;&#x7AEF;&#x7684;&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x673A;&#x5236;</li><li>Eureka&#x4E0E;ZK&#x7684;&#x6BD4;&#x8F83;<br>a. CAP&#x6A21;&#x578B;<br>b. &#x4F7F;&#x7528;&#x573A;&#x666F;</li></ol><h3 id="Eureka&#x9AD8;&#x53EF;&#x7528;&#x5B9E;&#x73B0;"><a href="#Eureka&#x9AD8;&#x53EF;&#x7528;&#x5B9E;&#x73B0;" class="headerlink" title="Eureka&#x9AD8;&#x53EF;&#x7528;&#x5B9E;&#x73B0;"></a>Eureka&#x9AD8;&#x53EF;&#x7528;&#x5B9E;&#x73B0;</h3><p>Eureka&#x7684;&#x9AD8;&#x53EF;&#x7528;&#x901A;&#x8FC7;&#x4EE5;&#x4E0B;&#x4E09;&#x70B9;&#x5B9E;&#x73B0;&#xFF1A;<br>a. eureka&#x5BA2;&#x6237;&#x7AEF;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x901A;&#x8BAF;&#x673A;&#x5236;<br>b. eureka&#x670D;&#x52A1;&#x7AEF;&#x4E0E;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x8282;&#x70B9;&#x7684;&#x901A;&#x8BAF;<br>c. eureka&#x670D;&#x52A1;&#x7AEF;&#x7684;&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x673A;&#x5236;</p><a id="more"></a><h4 id="eureka&#x5BA2;&#x6237;&#x7AEF;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x901A;&#x8BAF;&#x673A;&#x5236;"><a href="#eureka&#x5BA2;&#x6237;&#x7AEF;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x901A;&#x8BAF;&#x673A;&#x5236;" class="headerlink" title="eureka&#x5BA2;&#x6237;&#x7AEF;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x901A;&#x8BAF;&#x673A;&#x5236;"></a>eureka&#x5BA2;&#x6237;&#x7AEF;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x901A;&#x8BAF;&#x673A;&#x5236;</h4><p>&#x53EF;&#x4EE5;&#x770B;&#x4E0B;&#x5BA2;&#x6237;&#x7AEF;&#x4E0E;Eureka&#x670D;&#x52A1;&#x7AEF;&#x4E4B;&#x95F4;&#x7684;&#x901A;&#x8BAF;&#x7684;&#x6982;&#x8FF0;&#x6D41;&#x7A0B;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/152011.jpg" alt="&#x901A;&#x8BAF;"></p><p>&#x540C;&#x65F6;&#x4E3A;&#x4E86;&#x66F4;&#x597D;&#x7684;&#x8BF4;&#x660E;&#x9AD8;&#x53EF;&#x7528;&#x7684;&#x5B9E;&#x73B0;&#xFF0C;&#x5728;&#x8FD9;&#x91CC;&#x5927;&#x6982;&#x63CF;&#x8FF0;&#x4E00;&#x4E0B;Eureka&#x670D;&#x52A1;&#x7AEF;&#x7684;&#x5B58;&#x50A8;&#x7ED3;&#x6784;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/160441.jpg" alt="&#x5B58;&#x50A8;&#x7ED3;&#x6784;"></p><h5 id="&#x670D;&#x52A1;&#x6CE8;&#x518C;"><a href="#&#x670D;&#x52A1;&#x6CE8;&#x518C;" class="headerlink" title="&#x670D;&#x52A1;&#x6CE8;&#x518C;"></a>&#x670D;&#x52A1;&#x6CE8;&#x518C;</h5><ol><li><p>&#x5BA2;&#x6237;&#x7AEF;&#x8BF7;&#x6C42;<code>POST /eureka/v2/apps</code>&#x63A5;&#x53E3;&#xFF0C;&#x5C06;&#x5BA2;&#x6237;&#x7AEF;&#x7684;&#x670D;&#x52A1;&#x4FE1;&#x606F;&#x4E0A;&#x4F20;<br><code>PeerAwareInstanceRegistryImpl.java</code> 399&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;</span><br><span class="line"><span class="keyword">if</span> (info.getLeaseInfo() != <span class="keyword">null</span> &amp;&amp; info.getLeaseInfo().getDurationInSecs() &gt; <span class="number">0</span>) {</span><br><span class="line">    leaseDuration = info.getLeaseInfo().getDurationInSecs();</span><br><span class="line">}</span><br><span class="line"><span class="comment">// &#x672C;&#x5730;&#x6CE8;&#x518C;</span></span><br><span class="line"><span class="keyword">super</span>.register(info, leaseDuration, isReplication);</span><br><span class="line"><span class="comment">// &#x534F;&#x540C;&#x5176;&#x4ED6;eureka&#x670D;&#x52A1;&#x8282;&#x70B9;&#x540C;&#x6B65;&#x6CE8;&#x518C;</span></span><br><span class="line">replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, <span class="keyword">null</span>, isReplication);</span><br></pre></td></tr></tbody></table></figure></li><li><p>Eureka&#x670D;&#x52A1;&#x7AEF;&#x5C06;&#x5BA2;&#x6237;&#x7AEF;&#x4FE1;&#x606F;&#x4FDD;&#x5B58;&#x81F3;<code>Registry</code>&#x6CE8;&#x518C;&#x4FE1;&#x606F;&#x8F7D;&#x4F53;&#x5185;</p></li><li><p>&#x5C06;&#x6B64;&#x6B21;&#x6DFB;&#x52A0;&#x53D8;&#x66F4;&#x589E;&#x52A0;&#x5230;&#x53D8;&#x66F4;&#x961F;&#x5217;<br><code>AbstractInstanceRegistry.java</code> 194&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">register</span><span class="params">(InstanceInfo registrant, <span class="keyword">int</span> leaseDuration, <span class="keyword">boolean</span> isReplication)</span> </span>{</span><br><span class="line">    <span class="keyword">try</span> {</span><br><span class="line">        <span class="comment">// &#x8BFB;&#x9501;</span></span><br><span class="line">        read.lock();</span><br><span class="line">        <span class="comment">// &#x5B58;&#x50A8;&#x672C;&#x6B21;&#x6CE8;&#x518C;&#x4FE1;&#x606F;&#xFF08;appName -&gt; instanceId -&gt; instanceInfo&#xFF09;</span></span><br><span class="line">        Map&lt;String, Lease&lt;InstanceInfo&gt;&gt; gMap = registry.get(registrant.getAppName());</span><br><span class="line">        REGISTER.increment(isReplication);</span><br><span class="line">        <span class="keyword">if</span> (gMap == <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">final</span> ConcurrentHashMap&lt;String, Lease&lt;InstanceInfo&gt;&gt; gNewMap = <span class="keyword">new</span> ConcurrentHashMap&lt;String, Lease&lt;InstanceInfo&gt;&gt;();</span><br><span class="line">            gMap = registry.putIfAbsent(registrant.getAppName(), gNewMap);</span><br><span class="line">            <span class="keyword">if</span> (gMap == <span class="keyword">null</span>) {</span><br><span class="line">                gMap = gNewMap;</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// ...&#x5176;&#x4ED6;&#x903B;&#x8F91;</span></span><br><span class="line">        <span class="comment">// &#x5C06;&#x672C;&#x6B21;&#x6DFB;&#x52A0;&#x53D8;&#x66F4;&#x52A0;&#x5165;&#x6700;&#x8FD1;&#x53D8;&#x66F4;&#x961F;&#x5217;&#x5185;</span></span><br><span class="line">        recentlyChangedQueue.add(<span class="keyword">new</span> RecentlyChangedItem(lease));</span><br><span class="line">        <span class="comment">// &#x8BBE;&#x7F6E;&#x79DF;&#x7EA6;&#x7684;&#x4E0A;&#x4E00;&#x6B21;&#x66F4;&#x65B0;&#x65F6;&#x95F4;</span></span><br><span class="line">        registrant.setLastUpdatedTimestamp();   </span><br><span class="line">        <span class="comment">// &#x6267;&#x884C;&#x7F13;&#x5B58;&#x6E05;&#x7A7A;</span></span><br><span class="line">        invalidateCache(registrant.getAppName(), registrant.getVIPAddress(), registrant.getSecureVipAddress());</span><br><span class="line">    } <span class="keyword">finally</span> {</span><br><span class="line">        <span class="comment">// &#x8BFB;&#x9501;&#x89E3;&#x9501;</span></span><br><span class="line">        read.unlock();</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></li><li><p>&#x6E05;&#x7A7A;&#x8BFB;&#x5199;&#x7F13;&#x5B58;&#xFF08;&#x5148;&#x6E05;&#x7406;APP&#x3001;&#x518D;&#x6E05;&#x7406;ALL_APPS&#x3001;&#x6700;&#x540E;&#x6E05;&#x7406;ALL_APPS_DELTA&#xFF09;<br><code>ResponseCacheImpl.java</code> 251&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">invalidate</span><span class="params">(String appName, @Nullable String vipAddress, @Nullable String secureVipAddress)</span> </span>{</span><br><span class="line">    <span class="keyword">for</span> (Key.KeyType type : Key.KeyType.values()) {</span><br><span class="line">        <span class="keyword">for</span> (Version v : Version.values()) {</span><br><span class="line">            <span class="comment">// &#x5220;&#x9664;appName&#x672C;&#x8EAB;&#x7684;&#x7F13;&#x5B58;</span></span><br><span class="line">            <span class="comment">// &#x5220;&#x9664;ALL_APPS&#x7684;&#x7F13;&#x5B58;</span></span><br><span class="line">            <span class="comment">// &#x5220;&#x9664;ALL_APPS_DELTA&#x7684;&#x7F13;&#x5B58;</span></span><br><span class="line">            invalidate(</span><br><span class="line">                    <span class="keyword">new</span> Key(Key.EntityType.Application, appName, type, v, EurekaAccept.full),</span><br><span class="line">                    <span class="keyword">new</span> Key(Key.EntityType.Application, appName, type, v, EurekaAccept.compact),</span><br><span class="line">                    <span class="keyword">new</span> Key(Key.EntityType.Application, ALL_APPS, type, v, EurekaAccept.full),</span><br><span class="line">                    <span class="keyword">new</span> Key(Key.EntityType.Application, ALL_APPS, type, v, EurekaAccept.compact),</span><br><span class="line">                    <span class="keyword">new</span> Key(Key.EntityType.Application, ALL_APPS_DELTA, type, v, EurekaAccept.full),</span><br><span class="line">                    <span class="keyword">new</span> Key(Key.EntityType.Application, ALL_APPS_DELTA, type, v, EurekaAccept.compact)</span><br><span class="line">            );</span><br><span class="line">            <span class="comment">// &#x5B58;&#x5728;&#x865A;&#x62DF;&#x5730;&#x5740;&#x540D;&#x79F0;&#x7684;&#xFF0C;&#x5220;&#x9664;&#x865A;&#x62DF;&#x5730;&#x5740;&#x4E3A;key&#x7684;&#x7F13;&#x5B58;</span></span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">null</span> != vipAddress) {</span><br><span class="line">                invalidate(<span class="keyword">new</span> Key(Key.EntityType.VIP, vipAddress, type, v, EurekaAccept.full));</span><br><span class="line">            }</span><br><span class="line">            <span class="comment">// &#x5B58;&#x5728;&#x5B89;&#x5168;&#x865A;&#x62DF;&#x5730;&#x5740;&#x540D;&#x79F0;&#x7684;&#xFF0C;&#x5220;&#x9664;&#x5B89;&#x5168;&#x865A;&#x62DF;&#x5730;&#x5740;&#x4E3A;key&#x7684;&#x7F13;&#x5B58;</span></span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">null</span> != secureVipAddress) {</span><br><span class="line">                invalidate(<span class="keyword">new</span> Key(Key.EntityType.SVIP, secureVipAddress, type, v, EurekaAccept.full));</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></li></ol><p><code>ResponseCacheImpl.java</code> 277&#x884C;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">invalidate</span><span class="params">(Key... keys)</span> </span>{</span><br><span class="line">    <span class="keyword">for</span> (Key key : keys) {</span><br><span class="line">        <span class="comment">// Guava&#x7F13;&#x5B58;&#x5BF9;key&#x8BBE;&#x7F6E;&#x65E0;&#x6548;</span></span><br><span class="line">        readWriteCacheMap.invalidate(key);</span><br><span class="line">        Collection&lt;Key&gt; keysWithRegions = regionSpecificKeys.get(key);</span><br><span class="line">        <span class="comment">// key&#x5173;&#x8054;&#x533A;&#x57DF;&#x7684;&#x7F13;&#x5B58;&#x65E0;&#x6548;&#x8BBE;&#x7F6E;</span></span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><ol start="5"><li><p>&#x5224;&#x65AD;&#x4E0D;&#x5B58;&#x5B58;&#x5728;&#x5176;&#x4ED6;eureka&#x670D;&#x52A1;&#x8282;&#x70B9;&#xFF0C;&#x6216;&#x8005;&#x672C;&#x6B21;&#x8BF7;&#x6C42;&#x4E3A;&#x540C;&#x6B65;&#x8BF7;&#x6C42;&#x5219;&#x5B8C;&#x6210;&#x6CE8;&#x518C;<br><code>PeerAwareInstanceRegistryImpl.java</code> 620&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (peerEurekaNodes == Collections.EMPTY_LIST || isReplication) {</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></li><li><p>&#x5426;&#x5219;&#xFF0C;&#x83B7;&#x53D6;&#x6240;&#x6709;&#x5176;&#x4ED6;&#x7684;&#x670D;&#x52A1;&#x8282;&#x70B9;&#xFF0C;&#x6392;&#x9664;&#x672C;&#x8EAB;&#x670D;&#x52A1;&#xFF0C;&#x5C06;&#x672C;&#x6B21;&#x6CE8;&#x518C;&#x540C;&#x6B65;&#x81F3;&#x5176;&#x4ED6;eureka&#x670D;&#x52A1;&#x8282;&#x70B9;<br><code>PeerAwareInstanceRegistryImpl.java</code> 624&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">final</span> PeerEurekaNode node : peerEurekaNodes.getPeerEurekaNodes()) {</span><br><span class="line">    <span class="comment">// &#x6392;&#x9664;&#x81EA;&#x8EAB;</span></span><br><span class="line">    <span class="keyword">if</span> (peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {</span><br><span class="line">        <span class="keyword">continue</span>;</span><br><span class="line">    }</span><br><span class="line">    <span class="comment">// &#x540C;&#x6B65;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x8282;&#x70B9;</span></span><br><span class="line">    replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></li></ol><h5 id="&#x670D;&#x52A1;&#x7EED;&#x7EA6;"><a href="#&#x670D;&#x52A1;&#x7EED;&#x7EA6;" class="headerlink" title="&#x670D;&#x52A1;&#x7EED;&#x7EA6;"></a>&#x670D;&#x52A1;&#x7EED;&#x7EA6;</h5><ol><li>&#x5BA2;&#x6237;&#x7AEF;&#x8BF7;&#x6C42;<code>PUT /eureka/v2/apps/{appId}</code></li><li>&#x6839;&#x636E;appName&#x83B7;&#x53D6;&#x79DF;&#x7EA6;</li><li>&#x66F4;&#x65B0;&#x79DF;&#x7EA6;</li><li>&#x540C;&#x6B65;&#x81F3;&#x5176;&#x4ED6;eureka&#x670D;&#x52A1;&#x8282;&#x70B9;</li></ol><p>&#x7EED;&#x7EA6;&#x7C7B;&#x4F3C;&#x5FC3;&#x8DF3;&#x673A;&#x5236;&#xFF0C;&#x5BA2;&#x6237;&#x7AEF;&#x4F1A;&#x6309;&#x7167;&#x9ED8;&#x8BA4;&#x65F6;&#x95F4;&#x7684;30&#x79D2;&#x5B9A;&#x65F6;&#x505A;&#x4E00;&#x6B21;&#x7EED;&#x7EA6;&#xFF0C;&#x5982;&#x679C;&#x8D85;&#x8FC7;3&#x6B21;&#x6CA1;&#x6709;&#x6210;&#x529F;&#xFF0C;&#x5219;&#x670D;&#x52A1;&#x7AEF;&#x4F1A;&#x5C06;&#x8BE5;&#x5BA2;&#x6237;&#x7AEF;&#x5254;&#x9664;&#x3002;</p><h5 id="&#x670D;&#x52A1;&#x53D6;&#x6D88;&#x6CE8;&#x518C;"><a href="#&#x670D;&#x52A1;&#x53D6;&#x6D88;&#x6CE8;&#x518C;" class="headerlink" title="&#x670D;&#x52A1;&#x53D6;&#x6D88;&#x6CE8;&#x518C;"></a>&#x670D;&#x52A1;&#x53D6;&#x6D88;&#x6CE8;&#x518C;</h5><ol><li>&#x5BA2;&#x6237;&#x7AEF;&#x8BF7;&#x6C42;<code>DELETE /eureka/v2/apps/{appId}</code></li><li>&#x6839;&#x636E;appName&#x83B7;&#x53D6;&#x79DF;&#x7EA6;</li><li>&#x8BBE;&#x7F6E;&#x79DF;&#x7EA6;&#x8FC7;&#x671F;&#x65F6;&#x95F4;<code>evictionTimestamp</code>&#x4E3A;&#x5F53;&#x524D;&#x65F6;&#x95F4;</li><li>&#x5C06;&#x6B64;&#x6B21;&#x5220;&#x9664;&#x589E;&#x52A0;&#x5230;&#x53D8;&#x66F4;&#x961F;&#x5217;&#x4E2D;</li><li>&#x6E05;&#x7A7A;&#x8BFB;&#x5199;&#x7F13;&#x5B58;&#xFF08;&#x5148;&#x6E05;&#x7406;APP&#x3001;&#x518D;&#x6E05;&#x7406;ALL_APPS&#x3001;&#x6700;&#x540E;&#x6E05;&#x7406;ALL_APPS_DELTA&#xFF09;</li></ol><h5 id="&#x670D;&#x52A1;&#x5254;&#x9664;"><a href="#&#x670D;&#x52A1;&#x5254;&#x9664;" class="headerlink" title="&#x670D;&#x52A1;&#x5254;&#x9664;"></a>&#x670D;&#x52A1;&#x5254;&#x9664;</h5><ol><li><p>Eureka&#x670D;&#x52A1;&#x7AEF;&#x4F1A;&#x5728;&#x5185;&#x90E8;&#x4F1A;&#x521D;&#x59CB;&#x5316;&#x4E00;&#x4E2A;<code>Timer</code>&#x5B9A;&#x65F6;&#x5668;&#x7528;&#x4E8E;&#x5B9A;&#x65F6;&#x8C03;&#x5EA6;&#x5904;&#x7406;&#x5254;&#x9664;&#x4EFB;&#x52A1;&#xFF1B;&#x5254;&#x9664;&#x65F6;&#x95F4;&#x95F4;&#x9694;&#x4E3A;<code>evictionIntervalTimerInMs</code><br><code>AbstractInstanceRegistry.java</code> 1212&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">postInit</span><span class="params">()</span> </span>{</span><br><span class="line">   <span class="comment">// ....</span></span><br><span class="line">   <span class="comment">// &#x8BBE;&#x7F6E;&#x65B0;&#x7684;&#x8FC7;&#x671F;&#x4EFB;&#x52A1;</span></span><br><span class="line">   evictionTaskRef.set(<span class="keyword">new</span> EvictionTask());</span><br><span class="line">   <span class="comment">// &#x4EFB;&#x52A1;&#x8C03;&#x5EA6;</span></span><br><span class="line">   evictionTimer.schedule(evictionTaskRef.get(),</span><br><span class="line">            serverConfig.getEvictionIntervalTimerInMs(),</span><br><span class="line">            serverConfig.getEvictionIntervalTimerInMs());</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></li><li><p>&#x5224;&#x65AD;&#x662F;&#x5426;&#x542F;&#x7528;&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#xFF0C;&#x5982;&#x679C;&#x7981;&#x7528;&#xFF0C;&#x5219;&#x4E0D;&#x8FDB;&#x884C;&#x670D;&#x52A1;&#x5254;&#x9664;</p></li><li><p>&#x5224;&#x65AD; &#x4E0A;&#x4E00;&#x5206;&#x949F;&#x5B9E;&#x9645;&#x7684;&#x7EED;&#x7EA6;&#x6B21;&#x6570; &lt;= <code>numberOfRenewsPerMinThreshold</code>&#xFF0C;&#x5219;&#x4F1A;&#x89E6;&#x53D1;&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x673A;&#x5236;&#xFF0C;&#x505C;&#x6B62;&#x670D;&#x52A1;&#x5254;&#x9664;<br><code>PeerAwareInstanceRegistryImpl.java</code> 474&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5224;&#x65AD;&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x662F;&#x5426;&#x7981;&#x7528;</span></span><br><span class="line"><span class="keyword">if</span> (!isSelfPreservationModeEnabled()) {</span><br><span class="line">   <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">}</span><br><span class="line"><span class="comment">// &#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x673A;&#x5236;&#x9608;&#x503C;&#x5224;&#x65AD;</span></span><br><span class="line"><span class="keyword">return</span> numberOfRenewsPerMinThreshold &gt; <span class="number">0</span> &amp;&amp; getNumOfRenewsInLastMin() &gt; numberOfRenewsPerMinThreshold;</span><br></pre></td></tr></tbody></table></figure></li><li><p>&#x904D;&#x5386;<code>Registry</code>&#x5185;&#x6240;&#x6709;&#x7684;&#x79DF;&#x7EA6;&#x4FE1;&#x606F;&#xFF0C;&#x5224;&#x65AD;&#x5F53;&#x524D;&#x79DF;&#x7EA6;&#x662F;&#x5426;&#x8FC7;&#x671F;</p></li><li><p>&#x5C06;&#x8FD9;&#x4E9B;&#x8FC7;&#x671F;&#x7684;&#x79DF;&#x7EA6;&#x653E;&#x7F6E;&#x5230;&#x4E00;&#x4E2A;&#x8FC7;&#x671F;&#x5217;&#x8868;&#x5185;<br><code>AbstractInstanceRegistry.java</code> 597&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">List&lt;Lease&lt;InstanceInfo&gt;&gt; expiredLeases = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"><span class="comment">// &#x904D;&#x5386;&#x79DF;&#x7EA6;</span></span><br><span class="line"><span class="keyword">for</span> (Entry&lt;String, Map&lt;String, Lease&lt;InstanceInfo&gt;&gt;&gt; groupEntry : registry.entrySet()) {</span><br><span class="line">   Map&lt;String, Lease&lt;InstanceInfo&gt;&gt; leaseMap = groupEntry.getValue();</span><br><span class="line">   <span class="keyword">if</span> (leaseMap != <span class="keyword">null</span>) {</span><br><span class="line">         <span class="keyword">for</span> (Entry&lt;String, Lease&lt;InstanceInfo&gt;&gt; leaseEntry : leaseMap.entrySet()) {</span><br><span class="line">            Lease&lt;InstanceInfo&gt; lease = leaseEntry.getValue();</span><br><span class="line">            <span class="comment">// &#x5224;&#x65AD;&#x79DF;&#x7EA6;&#x662F;&#x5426;&#x8FC7;&#x671F;</span></span><br><span class="line">            <span class="comment">// additionalLeaseMs&#x662F;&#x8865;&#x507F;&#x65F6;&#x95F4;&#xFF0C;&#x9632;&#x6B62;&#x7531;&#x4E8E;GC&#x6216;&#x8005;&#x672C;&#x5730;&#x65F6;&#x95F4;&#x9020;&#x6210;&#x7684;&#x4E00;&#x4E2A;&#x65F6;&#x95F4;&#x8BEF;&#x5DEE;&#xFF0C;&#x786E;&#x4FDD;&#x80FD;&#x591F;&#x6309;&#x7167;&#x9884;&#x671F;&#x65F6;&#x95F4;&#x6267;&#x884C;</span></span><br><span class="line">            <span class="keyword">if</span> (lease.isExpired(additionalLeaseMs) &amp;&amp; lease.getHolder() != <span class="keyword">null</span>) {</span><br><span class="line">               <span class="comment">// &#x5C06;&#x8FC7;&#x671F;&#x79DF;&#x7EA6;&#x52A0;&#x5165;&#x8FC7;&#x671F;&#x5217;&#x8868;</span></span><br><span class="line">               expiredLeases.add(lease);</span><br><span class="line">            }</span><br><span class="line">         }</span><br><span class="line">   }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></li><li><p>&#x8BA1;&#x7B97;&#x53EF;&#x88AB;&#x5254;&#x9664;&#x7684;&#x8FC7;&#x671F;&#x5B9E;&#x4F8B;&#x6570;&#xFF08;&#x8FC7;&#x671F;&#x6570; = Math.min(&#x8FC7;&#x671F;&#x5217;&#x8868;&#x5927;&#x5C0F;, (&#x672C;&#x5730;&#x79DF;&#x7EA6;&#x6570; - &#x672C;&#x5730;&#x79DF;&#x7EA6;&#x6570; * &#x7EED;&#x7EA6;&#x767E;&#x5206;&#x6BD4;))&#xFF09;<br><code>AbstractInstanceRegistry.java</code> 612&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x83B7;&#x53D6;&#x672C;&#x5730;&#x79DF;&#x7EA6;&#x6570;</span></span><br><span class="line"><span class="keyword">int</span> registrySize = (<span class="keyword">int</span>) getLocalRegistrySize();</span><br><span class="line"><span class="comment">// &#x8BA1;&#x7B97;&#x79DF;&#x7EA6;</span></span><br><span class="line"><span class="keyword">int</span> registrySizeThreshold = (<span class="keyword">int</span>) (registrySize * serverConfig.getRenewalPercentThreshold());</span><br><span class="line"><span class="comment">// &#x5B9E;&#x9645;&#x9700;&#x8981;&#x5254;&#x9664;&#x7684;&#x79DF;&#x7EA6;&#x4E2A;&#x6570;</span></span><br><span class="line"><span class="keyword">int</span> evictionLimit = registrySize - registrySizeThreshold;</span><br></pre></td></tr></tbody></table></figure></li><li><p>&#x4F7F;&#x7528;&#x6D17;&#x724C;&#x7B97;&#x6CD5;&#x627E;&#x51FA;&#x9700;&#x8981;&#x5254;&#x9664;&#x7684;n&#x4E2A;&#x5B9E;&#x4F8B;<br><code>AbstractInstanceRegistry.java</code> 620&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x6309;&#x7167;&#x5254;&#x9664;&#x6570;&#x904D;&#x5386;&#xFF0C;&#x6BCF;&#x6B21;&#x7684;&#x4EA4;&#x6362;&#x5BF9;&#x8C61;&#x90FD;&#x662F;&#x57FA;&#x4E8E;&#x4E0A;&#x6B21;&#x7684;&#x968F;&#x673A;&#x7ED3;&#x679C;</span></span><br><span class="line">Random random = <span class="keyword">new</span> Random(System.currentTimeMillis());</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; toEvict; i++) {</span><br><span class="line">   <span class="comment">// &#x7B5B;&#x9009;&#x51FA;&#x9700;&#x8981;&#x4EA4;&#x6362;&#x4F4D;&#x7F6E;&#x7684;&#x7D22;&#x5F15;next&#x5E76;&#x4E0E;i&#x4EA4;&#x6362;&#x4F4D;&#x7F6E;</span></span><br><span class="line">   <span class="keyword">int</span> next = i + random.nextInt(expiredLeases.size() - i);</span><br><span class="line">   Collections.swap(expiredLeases, i, next);</span><br><span class="line">   <span class="comment">// &#x5254;&#x9664;&#x903B;&#x8F91;</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></li><li><p>&#x8BBE;&#x7F6E;&#x79DF;&#x7EA6;&#x8FC7;&#x671F;&#x65F6;&#x95F4;<code>evictionTimestamp</code>&#x4E3A;&#x5F53;&#x524D;&#x65F6;&#x95F4;</p></li><li>&#x5C06;&#x6B64;&#x6B21;&#x5220;&#x9664;&#x589E;&#x52A0;&#x5230;&#x53D8;&#x66F4;&#x961F;&#x5217;&#x4E2D;</li><li>&#x6E05;&#x7A7A;&#x8BFB;&#x5199;&#x7F13;&#x5B58;</li></ol><h4 id="eureka&#x670D;&#x52A1;&#x7AEF;&#x4E0E;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x8282;&#x70B9;&#x7684;&#x901A;&#x8BAF;"><a href="#eureka&#x670D;&#x52A1;&#x7AEF;&#x4E0E;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x8282;&#x70B9;&#x7684;&#x901A;&#x8BAF;" class="headerlink" title="eureka&#x670D;&#x52A1;&#x7AEF;&#x4E0E;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x8282;&#x70B9;&#x7684;&#x901A;&#x8BAF;"></a>eureka&#x670D;&#x52A1;&#x7AEF;&#x4E0E;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x8282;&#x70B9;&#x7684;&#x901A;&#x8BAF;</h4><p>eureka&#x670D;&#x52A1;&#x7AEF;&#x4E0E;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x8282;&#x70B9;&#x7684;&#x901A;&#x8BAF;&#x4E3B;&#x8981;&#x5305;&#x542B;&#x4E24;&#x90E8;&#x5206;&#xFF1A;</p><ol><li>eureka&#x670D;&#x52A1;&#x7AEF;&#x542F;&#x52A8;&#x65F6;&#x5019;&#x81EA;&#x52A8;&#x62C9;&#x53D6;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x8282;&#x70B9;&#x7684;&#x6CE8;&#x518C;&#x4FE1;&#x606F;&#x5E76;&#x843D;&#x5165;&#x672C;&#x5730;<code>Registry</code>&#x4E2D;</li><li>&#x4E00;&#x65E6;&#x6709;&#x8BF8;&#x5982;<code>register</code>,<code>renew</code>,<code>cancel</code>&#x8BF7;&#x6C42;&#xFF0C;&#x5219;&#x4F1A;&#x5C06;&#x8FD9;&#x4E9B;&#x8BF7;&#x6C42;&#x901A;&#x8FC7;&#x7EBF;&#x7A0B;&#x6C60;&#x81EA;&#x52A8;&#x540C;&#x6B65;&#x81F3;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x8282;&#x70B9;</li></ol><h5 id="&#x542F;&#x52A8;&#x521D;&#x59CB;&#x5316;"><a href="#&#x542F;&#x52A8;&#x521D;&#x59CB;&#x5316;" class="headerlink" title="&#x542F;&#x52A8;&#x521D;&#x59CB;&#x5316;"></a>&#x542F;&#x52A8;&#x521D;&#x59CB;&#x5316;</h5><ol><li><p>Servlet&#x5BB9;&#x5668;&#x521D;&#x59CB;&#x5316;&#xFF0C;&#x8C03;&#x7528;eureka&#x73AF;&#x5883;&#x521D;&#x59CB;&#x5316;&#x4EE5;&#x53CA;eureka&#x4E0A;&#x4E0B;&#x6587;&#x521D;&#x59CB;&#x5316;<br><code>EurekaBootstrap.java</code> 111&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">contextInitialized</span><span class="params">(ServletContextEvent event)</span> </span>{</span><br><span class="line">    <span class="keyword">try</span> {</span><br><span class="line">        <span class="comment">// &#x521D;&#x59CB;&#x5316;&#x73AF;&#x5883;</span></span><br><span class="line">        initEurekaEnvironment();</span><br><span class="line">        <span class="comment">// &#x521D;&#x59CB;&#x5316;&#x4E0A;&#x4E0B;&#x6587;</span></span><br><span class="line">        initEurekaServerContext();</span><br><span class="line"></span><br><span class="line">        ServletContext sc = event.getServletContext();</span><br><span class="line">        sc.setAttribute(EurekaServerContext.class.getName(), serverContext);</span><br><span class="line">    } <span class="keyword">catch</span> (Throwable e) {</span><br><span class="line">        logger.error(<span class="string">&quot;Cannot bootstrap eureka server :&quot;</span>, e);</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(<span class="string">&quot;Cannot bootstrap eureka server :&quot;</span>, e);</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></li><li><p>&#x521D;&#x59CB;&#x5316;&#x4E0A;&#x4E0B;&#x6587;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#x4F1A;&#x5F00;&#x59CB;&#x540C;&#x6B65;&#x5176;&#x4ED6;eureka&#x670D;&#x52A1;&#x8282;&#x70B9;&#x7684;&#x4FE1;&#x606F;<br><code>EurekaBootstrap.java</code> 147&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">initEurekaServerContext</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>{</span><br><span class="line">    <span class="comment">// ...&#x5176;&#x4ED6;&#x903B;&#x8F91;</span></span><br><span class="line">    ApplicationInfoManager applicationInfoManager = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x521D;&#x59CB;&#x5316;eureka&#x5BA2;&#x6237;&#x7AEF;&#xFF0C;&#x7528;&#x4E8E;&#x505A;&#x4E3A;&#x83B7;&#x53D6;&#x5176;&#x4ED6;eureka&#x670D;&#x52A1;&#x4FE1;&#x606F;&#x7684;client</span></span><br><span class="line">    <span class="keyword">if</span> (eurekaClient == <span class="keyword">null</span>) {</span><br><span class="line">        EurekaInstanceConfig instanceConfig = isCloud(ConfigurationManager.getDeploymentContext())</span><br><span class="line">                ? <span class="keyword">new</span> CloudInstanceConfig()</span><br><span class="line">                : <span class="keyword">new</span> MyDataCenterInstanceConfig();</span><br><span class="line">        </span><br><span class="line">        applicationInfoManager = <span class="keyword">new</span> ApplicationInfoManager(</span><br><span class="line">                instanceConfig, <span class="keyword">new</span> EurekaConfigBasedInstanceInfoProvider(instanceConfig).get());</span><br><span class="line">        </span><br><span class="line">        EurekaClientConfig eurekaClientConfig = <span class="keyword">new</span> DefaultEurekaClientConfig();</span><br><span class="line">        eurekaClient = <span class="keyword">new</span> DiscoveryClient(applicationInfoManager, eurekaClientConfig);</span><br><span class="line">    } <span class="keyword">else</span> {</span><br><span class="line">        applicationInfoManager = eurekaClient.getApplicationInfoManager();</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x521D;&#x59CB;&#x5316;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x5B9E;&#x4F8B;&#x611F;&#x77E5;&#x7684;&#x6CE8;&#x518C;&#x5668;</span></span><br><span class="line">    PeerAwareInstanceRegistry registry;</span><br><span class="line">    <span class="keyword">if</span> (isAws(applicationInfoManager.getInfo())) {</span><br><span class="line">        <span class="comment">// aws &#x670D;&#x52A1;</span></span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    } <span class="keyword">else</span> {</span><br><span class="line">        registry = <span class="keyword">new</span> PeerAwareInstanceRegistryImpl(</span><br><span class="line">                eurekaServerConfig,</span><br><span class="line">                eurekaClient.getEurekaClientConfig(),</span><br><span class="line">                serverCodecs,</span><br><span class="line">                eurekaClient</span><br><span class="line">        );</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x4E3A;&#x5176;&#x4ED6;eureka&#x670D;&#x52A1;&#x6CE8;&#x518C;eurekaNode&#x5B9E;&#x4F8B;</span></span><br><span class="line">    PeerEurekaNodes peerEurekaNodes = getPeerEurekaNodes(</span><br><span class="line">            registry,</span><br><span class="line">            eurekaServerConfig,</span><br><span class="line">            eurekaClient.getEurekaClientConfig(),</span><br><span class="line">            serverCodecs,</span><br><span class="line">            applicationInfoManager</span><br><span class="line">    );</span><br><span class="line"></span><br><span class="line">    <span class="comment">// servlet&#x5BB9;&#x5668;&#x521D;&#x59CB;&#x5316;</span></span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x4ECE;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x62F7;&#x8D1D;&#x6CE8;&#x518C;&#x4FE1;&#x606F;</span></span><br><span class="line">    <span class="keyword">int</span> registryCount = registry.syncUp();</span><br><span class="line">    <span class="comment">// &#x7B49;&#x5F85;&#x63A5;&#x6536;&#x8BF7;&#x6C42;</span></span><br><span class="line">    registry.openForTraffic(applicationInfoManager, registryCount);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x5176;&#x4ED6;&#x64CD;&#x4F5C;</span></span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></li></ol><p>&#x540C;&#x6B65;&#x903B;&#x8F91;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">syncUp</span><span class="params">()</span> </span>{</span><br><span class="line">    <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x5C1D;&#x8BD5;&#x540C;&#x6B65;&#x76F4;&#x5230;&#x8FBE;&#x5230;&#x6700;&#x5927;&#x5C1D;&#x8BD5;&#x6B21;&#x6570;</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; ((i &lt; serverConfig.getRegistrySyncRetries()) &amp;&amp; (count == <span class="number">0</span>)); i++) {</span><br><span class="line">        <span class="keyword">if</span> (i &gt; <span class="number">0</span>) {</span><br><span class="line">            <span class="comment">// &#x5C1D;&#x8BD5;&#x95F4;&#x9694;&#x7761;&#x7720;&#x65F6;&#x95F4;</span></span><br><span class="line">            <span class="comment">// ...</span></span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// &#x83B7;&#x53D6;&#x6240;&#x6709;&#x7684;&#x5E94;&#x7528;</span></span><br><span class="line">        Applications apps = eurekaClient.getApplications();</span><br><span class="line">        <span class="comment">// &#x83B7;&#x53D6;&#x6240;&#x6709;&#x6CE8;&#x518C;&#x7684;&#x5E94;&#x7528;</span></span><br><span class="line">        <span class="keyword">for</span> (Application app : apps.getRegisteredApplications()) {</span><br><span class="line">            <span class="keyword">for</span> (InstanceInfo instance : app.getInstances()) {</span><br><span class="line">                <span class="keyword">try</span> {</span><br><span class="line">                    <span class="comment">// &#x5224;&#x65AD;&#x5E94;&#x7528;&#x662F;&#x5426;&#x5728;&#x5F53;&#x524D;&#x533A;&#x57DF;&#x6CE8;&#x518C;</span></span><br><span class="line">                    <span class="comment">// &#x8BE5;&#x914D;&#x7F6E;&#x53EA;&#x5BF9;&#x4E8E;AWS&#x6709;&#x6548;&#xFF0C;&#x5176;&#x4ED6;&#x975E;AWS&#x670D;&#x52A1;&#x5168;&#x90E8;&#x4F1A;&#x62C9;&#x53D6;</span></span><br><span class="line">                    <span class="keyword">if</span> (isRegisterable(instance)) {</span><br><span class="line">                        <span class="comment">// &#x662F;&#xFF0C;&#x5219;&#x843D;&#x5165;&#x672C;&#x5730;&#x5185;&#x5B58;</span></span><br><span class="line">                        register(instance, instance.getLeaseInfo().getDurationInSecs(), <span class="keyword">true</span>);</span><br><span class="line">                        count++;</span><br><span class="line">                    }</span><br><span class="line">                } <span class="keyword">catch</span> (Throwable t) {</span><br><span class="line">                    logger.error(<span class="string">&quot;During DS init copy&quot;</span>, t);</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">return</span> count;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><ol start="3"><li>&#x5B8C;&#x6210;&#x540E;&#x5F00;&#x59CB;&#x63A5;&#x6536;&#x8BF7;&#x6C42;</li></ol><h5 id="&#x8FC7;&#x7A0B;&#x4E2D;&#x540C;&#x6B65;"><a href="#&#x8FC7;&#x7A0B;&#x4E2D;&#x540C;&#x6B65;" class="headerlink" title="&#x8FC7;&#x7A0B;&#x4E2D;&#x540C;&#x6B65;"></a>&#x8FC7;&#x7A0B;&#x4E2D;&#x540C;&#x6B65;</h5><p>&#x4EE5;&#x6CE8;&#x518C;&#x540C;&#x6B65;&#x4E3A;&#x4F8B;&#x5B50;&#x3002;</p><ol><li><p>&#x6839;&#x636E;&#x8BF7;&#x6C42;&#x7C7B;&#x578B;&#x5224;&#x65AD;&#x6267;&#x884C;&#x52A8;&#x4F5C;<br><code>PeerAwareInstanceRegistry.java</code> 648&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">case</span> Cancel:</span><br><span class="line">    node.cancel(appName, id);</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> Heartbeat:</span><br><span class="line">    InstanceStatus overriddenStatus = overriddenInstanceStatusMap.get(id);</span><br><span class="line">    infoFromRegistry = getInstanceByAppAndId(appName, id, <span class="keyword">false</span>);</span><br><span class="line">    node.heartbeat(appName, id, infoFromRegistry, overriddenStatus, <span class="keyword">false</span>);</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> Register:</span><br><span class="line">    <span class="comment">// &#x8C03;&#x7528;PeerEurekaNode&#x7684;register&#x65B9;&#x6CD5;&#x6267;&#x884C;&#x6CE8;&#x518C;&#x52A8;&#x4F5C;&#x7684;&#x540C;&#x6B65;</span></span><br><span class="line">    node.register(info);</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> StatusUpdate:</span><br><span class="line">    infoFromRegistry = getInstanceByAppAndId(appName, id, <span class="keyword">false</span>);</span><br><span class="line">    node.statusUpdate(appName, id, newStatus, infoFromRegistry);</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> DeleteStatusOverride:</span><br><span class="line">    infoFromRegistry = getInstanceByAppAndId(appName, id, <span class="keyword">false</span>);</span><br><span class="line">    node.deleteStatusOverride(appName, id, infoFromRegistry);</span><br><span class="line">    <span class="keyword">break</span>;</span><br></pre></td></tr></tbody></table></figure></li><li><p>&#x5C06;&#x4EFB;&#x52A1;&#x63D0;&#x4EA4;&#x81F3;&#x4EFB;&#x52A1;&#x5904;&#x7406;&#x5668;<code>TaskDispatcher</code>&#x8FDB;&#x884C;<br><code>PeerEurekaNode.java</code> 135&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">long</span> expiryTime = System.currentTimeMillis() + getLeaseRenewalOf(info);</span><br><span class="line">batchingDispatcher.process(</span><br><span class="line">        taskId(<span class="string">&quot;register&quot;</span>, info),</span><br><span class="line">        <span class="comment">// &#x540C;&#x6B65;&#x4EFB;&#x52A1;&#x4FE1;&#x606F;</span></span><br><span class="line">        <span class="keyword">new</span> InstanceReplicationTask(targetHost, Action.Register, info, <span class="keyword">null</span>, <span class="keyword">true</span>) {</span><br><span class="line">            <span class="function"><span class="keyword">public</span> EurekaHttpResponse&lt;Void&gt; <span class="title">execute</span><span class="params">()</span> </span>{</span><br><span class="line">                <span class="keyword">return</span> replicationClient.register(info);</span><br><span class="line">            }</span><br><span class="line">        },</span><br><span class="line">        expiryTime</span><br><span class="line">);</span><br></pre></td></tr></tbody></table></figure></li><li><p>&#x8C03;&#x7528;Jersey2&#x6267;&#x884C;REST&#x8BF7;&#x6C42;<br><code>AbstractJersey2EurekaHttpClient.java</code> 85&#x884C;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> EurekaHttpResponse&lt;Void&gt; <span class="title">register</span><span class="params">(InstanceInfo info)</span> </span>{</span><br><span class="line">    String urlPath = <span class="string">&quot;apps/&quot;</span> + info.getAppName();</span><br><span class="line">    Response response = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">try</span> {</span><br><span class="line">        <span class="comment">// &#x5C01;&#x88C5;&#x8BF7;&#x6C42;</span></span><br><span class="line">        Builder resourceBuilder = jerseyClient.target(serviceUrl).path(urlPath).request();</span><br><span class="line">        addExtraProperties(resourceBuilder);</span><br><span class="line">        <span class="comment">// &#x8BBE;&#x7F6E;x-netflix-discovery-replication&#x5934;&#x4FE1;&#x606F;&#x4E3A;true&#xFF0C;&#x5176;&#x4ED6;eureka&#x670D;&#x52A1;&#x8282;&#x70B9;&#x63A5;&#x6536;&#x540E;&#x4F1A;&#x77E5;&#x6653;&#x8FD9;&#x662F;&#x4E2A;&#x540C;&#x6B65;&#x8BF7;&#x6C42;</span></span><br><span class="line">        addExtraHeaders(resourceBuilder);</span><br><span class="line">        <span class="comment">// &#x6267;&#x884C;&#x8BF7;&#x6C42;&#x5E76;&#x83B7;&#x53D6;&#x7ED3;&#x679C;</span></span><br><span class="line">        response = resourceBuilder</span><br><span class="line">                .accept(MediaType.APPLICATION_JSON)</span><br><span class="line">                .acceptEncoding(<span class="string">&quot;gzip&quot;</span>)</span><br><span class="line">                .post(Entity.json(info));</span><br><span class="line">        <span class="keyword">return</span> anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();</span><br><span class="line">    } <span class="keyword">finally</span> {</span><br><span class="line">        <span class="keyword">if</span> (logger.isDebugEnabled()) {</span><br><span class="line">            logger.debug(<span class="string">&quot;Jersey2 HTTP POST {}/{} with instance {}; statusCode={}&quot;</span>, serviceUrl, urlPath, info.getId(),</span><br><span class="line">                    response == <span class="keyword">null</span> ? <span class="string">&quot;N/A&quot;</span> : response.getStatus());</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">if</span> (response != <span class="keyword">null</span>) {</span><br><span class="line">            response.close();</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></li></ol><h4 id="Eureka&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x673A;&#x5236;"><a href="#Eureka&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x673A;&#x5236;" class="headerlink" title="Eureka&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x673A;&#x5236;"></a>Eureka&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x673A;&#x5236;</h4><p>Eureka&#x662F;Netflix&#x4E3A;&#x4E86;&#x89E3;&#x51B3;&#x73B0;&#x6709;AWS&#x7684;&#x6CE8;&#x518C;&#x670D;&#x52A1;&#x65E0;&#x6CD5;&#x89E3;&#x51B3;&#x7684;&#x4E00;&#x4E9B;&#x573A;&#x666F;&#x800C;&#x4E13;&#x95E8;&#x7814;&#x53D1;&#x7684;&#x3002;&#x5728;&#x8BBE;&#x8BA1;&#x4E4B;&#x521D;&#xFF0C;&#x5C31;&#x8003;&#x8651;&#x5230;&#x9AD8;&#x53EF;&#x7528;&#x7279;&#x6027;&#xFF0C;&#x9632;&#x6B62;AWS&#x7A81;&#x7136;&#x6027;&#x7684;&#x5927;&#x89C4;&#x6A21;&#x65AD;&#x70B9;&#x9020;&#x6210;&#x670D;&#x52A1;&#x4E0D;&#x53EF;&#x7528;&#x7684;&#x60C5;&#x51B5;&#x8BBE;&#x8BA1;&#x4E86;Eureka&#x7684;&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x673A;&#x5236;&#x3002;</p><p>Eureka&#x7684;&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x673A;&#x5236;&#x8BBE;&#x5B9A;&#x4E3A;&#xFF1A;&#x670D;&#x52A1;&#x603B;&#x6570; <em>&#x6BCF;&#x5206;&#x949F;&#x7EED;&#x7EA6;&#x6570;&#xFF08;60s / &#x5BA2;&#x6237;&#x7AEF;&#x7EED;&#x7EA6;&#x95F4;&#x9694;&#xFF09; </em>&#x81EA;&#x6211;&#x4FDD;&#x62A4;&#x9608;&#x503C;&#x56E0;&#x5B50;</p><p>&#x4E3E;&#x4E2A;&#x4F8B;&#x5B50;&#x8BF4;&#x660E;&#xFF1A;<br>&#x5982;&#x679C;&#x67D0;&#x4E2A;&#x5E94;&#x7528;A&#x6709;100&#x4E2A;&#x670D;&#x52A1;&#x5B9E;&#x4F8B;&#xFF0C;&#x90A3;&#x4E48;&#x6309;&#x7167;&#x516C;&#x5F0F;&#x8BA1;&#x7B97;&#xFF0C;&#x5B83;&#x5728;&#x4E00;&#x5206;&#x949F;&#x5185;&#x7EED;&#x7EA6;&#x6B21;&#x6570;&#x5FC5;&#x987B; &gt;= 170&#x3002;</p><p>&#x5982;&#x679C;&#x5728;&#x4E0A;&#x4E00;&#x4E2A;&#x5206;&#x949F;&#x5185;&#xFF0C;&#x7EED;&#x7EA6;&#x6570; &gt; 170&#xFF0C;&#x90A3;&#x4E48;&#x670D;&#x52A1;&#x6B63;&#x5E38;&#xFF0C;&#x67D0;&#x4E2A;&#x5B9E;&#x4F8B;&#x5C31;&#x7B97;&#x5931;&#x8D25;&#x4E5F;&#x53EA;&#x4F1A;&#x8BA4;&#x4E3A;&#x662F;&#x5BA2;&#x6237;&#x7AEF;&#x5B58;&#x5728;&#x95EE;&#x9898;&#xFF0C;&#x4F1A;&#x88AB;&#x5254;&#x9664;&#xFF1B;<br>&#x5982;&#x679C;&#x5728;&#x4E0A;&#x4E00;&#x4E2A;&#x5206;&#x949F;&#x5185;&#xFF0C;&#x7EED;&#x7EA6;&#x6570; &lt; 170&#xFF0C;&#x90A3;&#x4E48;Eureka&#x5C31;&#x4F1A;&#x8BA4;&#x4E3A;&#x662F;Eureka&#x670D;&#x52A1;&#x5B58;&#x5728;&#x95EE;&#x9898;&#xFF0C;&#x4F1A;&#x505C;&#x6B62;&#x5254;&#x9664;&#x6D41;&#x7A0B;&#xFF0C;&#x4FDD;&#x62A4;&#x73B0;&#x6709;&#x7684;&#x6CE8;&#x518C;&#x4FE1;&#x606F;&#xFF0C;&#x9632;&#x6B62;&#x670D;&#x52A1;&#x5927;&#x89C4;&#x6A21;&#x4E0B;&#x7EBF;&#x3002;</p><h3 id="Eureka&#x4E0E;ZK&#x7684;&#x6BD4;&#x8F83;"><a href="#Eureka&#x4E0E;ZK&#x7684;&#x6BD4;&#x8F83;" class="headerlink" title="Eureka&#x4E0E;ZK&#x7684;&#x6BD4;&#x8F83;"></a>Eureka&#x4E0E;ZK&#x7684;&#x6BD4;&#x8F83;</h3><h4 id="CAP&#x6A21;&#x578B;"><a href="#CAP&#x6A21;&#x578B;" class="headerlink" title="CAP&#x6A21;&#x578B;"></a>CAP&#x6A21;&#x578B;</h4><p><img src="https://static.xuqiang.me/public/images/182704.jpg" alt="CAP&#x6A21;&#x578B;"></p><p>Eureka&#x662F;AP&#x6A21;&#x578B;&#xFF0C;ZK&#x662F;CP&#x6A21;&#x578B;&#x3002;&#x524D;&#x8005;&#x5F3A;&#x8C03;&#x9AD8;&#x53EF;&#x7528;&#xFF0C;&#x5373;&#x4F7F;&#x5728;&#x67D0;&#x4E9B;&#x60C5;&#x51B5;&#x4E0B;&#x4E0D;&#x540C;region&#x770B;&#x5230;&#x7684;&#x89C6;&#x56FE;&#x53EF;&#x80FD;&#x4E0D;&#x4E00;&#x81F4;&#xFF1B;&#x800C;&#x540E;&#x8005;&#x5F3A;&#x8C03;&#x7684;&#x662F;&#x5F3A;&#x4E00;&#x81F4;&#x6027;&#xFF0C;&#x4E14;&#x5728;&#x8D85;&#x8FC7;&#x4E00;&#x5B9A;&#x9608;&#x503C;&#x540E;&#x4F1A;&#x9020;&#x6210;ZK&#x96C6;&#x7FA4;&#x6574;&#x4F53;&#x4E0D;&#x53EF;&#x7528;</p><h4 id="&#x5E94;&#x7528;&#x573A;&#x666F;"><a href="#&#x5E94;&#x7528;&#x573A;&#x666F;" class="headerlink" title="&#x5E94;&#x7528;&#x573A;&#x666F;"></a>&#x5E94;&#x7528;&#x573A;&#x666F;</h4><table><thead><tr><th>&#x573A;&#x666F;</th><th>Eureka</th><th>ZK</th></tr></thead><tbody><tr><td>&#x6570;&#x636E;&#x5206;&#x53D1;&#x548C;&#x8BA2;&#x9605;</td><td>&#xD7;</td><td>&#x221A;</td></tr><tr><td>&#x5F02;&#x5730;&#x5927;&#x89C4;&#x6A21;&#x96C6;&#x7FA4;&#x9700;&#x6C42;&#x7684;&#x6CE8;&#x518C;&#x4E2D;&#x5FC3;</td><td>&#x221A;</td><td>&#xD7;</td></tr><tr><td>&#x5C0F;&#x89C4;&#x6A21;&#x5355;&#x673A;&#x623F;&#x6CE8;&#x518C;&#x4E2D;&#x5FC3;</td><td>&#x221A;</td><td>&#x221A;</td></tr></tbody></table><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;概览&quot;&gt;&lt;a href=&quot;#概览&quot; class=&quot;headerlink&quot; title=&quot;概览&quot;&gt;&lt;/a&gt;概览&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;https://static.xuqiang.me/public/images/161317.jpg&quot; alt=&quot;Eureka高可用架构&quot;&gt;&lt;/p&gt;&lt;p&gt;本文分以下几点：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Eureka的高可用实现&lt;br&gt;a. eureka客户端与服务端通讯机制&lt;br&gt;b. eureka服务端与其他服务节点的通讯&lt;br&gt;c. eureka服务端的自我保护机制&lt;/li&gt;&lt;li&gt;Eureka与ZK的比较&lt;br&gt;a. CAP模型&lt;br&gt;b. 使用场景&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;Eureka高可用实现&quot;&gt;&lt;a href=&quot;#Eureka高可用实现&quot; class=&quot;headerlink&quot; title=&quot;Eureka高可用实现&quot;&gt;&lt;/a&gt;Eureka高可用实现&lt;/h3&gt;&lt;p&gt;Eureka的高可用通过以下三点实现：&lt;br&gt;a. eureka客户端与服务端通讯机制&lt;br&gt;b. eureka服务端与其他服务节点的通讯&lt;br&gt;c. eureka服务端的自我保护机制&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="Eureka" scheme="https://xuqiang.me/categories/Java/Eureka/"/>
    
      <category term="EurekaSources" scheme="https://xuqiang.me/categories/Java/Eureka/EurekaSources/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="eureka" scheme="https://xuqiang.me/tags/eureka/"/>
    
      <category term="HA" scheme="https://xuqiang.me/tags/HA/"/>
    
  </entry>
  
  <entry>
    <title>如何系统性的学习分析一个开源框架</title>
    <link href="https://xuqiang.me/how-to-learn-opensource-framework.html"/>
    <id>https://xuqiang.me/how-to-learn-opensource-framework.html</id>
    <published>2020-01-23T14:23:07.000Z</published>
    <updated>2020-08-03T16:15:13.849Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x8FD9;&#x51E0;&#x5E74;&#x5DE5;&#x4F5C;&#x5B66;&#x4E60;&#x4E0B;&#x6765;&#xFF0C;&#x5BF9;&#x4E8E;&#x5F00;&#x6E90;&#x6846;&#x67B6;&#x5206;&#x6790;&#x5B66;&#x4E60;&#x6CA1;&#x6709;&#x4E00;&#x4E2A;&#x5B8C;&#x5584;&#x7684;&#x65B9;&#x6CD5;&#x8BBA;&#x53EF;&#x4F9B;&#x53C2;&#x8003;&#xFF0C;&#x7ED3;&#x5408;&#x81EA;&#x8EAB;&#x7684;&#x5B66;&#x4E60;&#x7ECF;&#x9A8C;&#xFF0C;&#x5728;&#x8FD9;&#x91CC;&#x7565;&#x5FAE;&#x53D1;&#x8868;&#x4E0B;&#x7B14;&#x8005;&#x7684;&#x601D;&#x8DEF;&#x3002;</p><h3 id="&#x6307;&#x5BFC;&#x601D;&#x60F3;"><a href="#&#x6307;&#x5BFC;&#x601D;&#x60F3;" class="headerlink" title="&#x6307;&#x5BFC;&#x601D;&#x60F3;"></a>&#x6307;&#x5BFC;&#x601D;&#x60F3;</h3><ol><li>&#x9996;&#x5148;&#x9700;&#x8981;&#x4E86;&#x89E3;&#x8FD9;&#x4E2A;&#x5F00;&#x6E90;&#x6846;&#x67B6;&#x7684;&#x6846;&#x67B6;&#x6027;&#x529F;&#x80FD;&#xFF08;&#x5982;&#x679C;&#x6587;&#x6863;&#x6CA1;&#x6709;&#xFF0C;&#x5219;&#x901A;&#x8FC7;&#x8FD9;&#x4E2A;&#x6846;&#x67B6;&#x7684;&#x5177;&#x4F53;&#x529F;&#x80FD;&#x6765;&#x63D0;&#x53D6;&#x8981;&#x7D20;&#xFF0C;&#x627E;&#x5230;&#x6846;&#x67B6;&#x6027;&#x529F;&#x80FD;&#xFF09;</li><li>&#x5206;&#x6790;&#x4E0D;&#x540C;&#x6846;&#x67B6;&#x6027;&#x529F;&#x80FD;&#x5728;&#x8FD9;&#x4E2A;&#x6846;&#x67B6;&#x5185;&#x7684;&#x4F5C;&#x7528;&#xFF08;&#x6838;&#x5FC3;&#x529F;&#x80FD;&#x3001;&#x652F;&#x6491;&#x529F;&#x80FD;&#xFF09;</li><li>&#x5BF9;&#x4E8E;&#x6838;&#x5FC3;&#x529F;&#x80FD;&#x5177;&#x4F53;&#x5206;&#x6790;&#xFF0C;&#x5BF9;&#x4E8E;&#x652F;&#x6491;&#x529F;&#x80FD;&#x6709;&#x5174;&#x8DA3;&#x518D;&#x4E86;&#x89E3;</li><li>&#x6838;&#x5FC3;&#x529F;&#x80FD;&#x5206;&#x6790;&#xFF0C;&#x6309;&#x7167;&#x4E0A;&#x8FF0;2&#x3001;3&#x7684;&#x903B;&#x8F91;&#x518D;&#x505A;&#x5177;&#x4F53;&#x529F;&#x80FD;&#x7684;&#x62C6;&#x5206;&#xFF0C;&#x57FA;&#x672C;&#x4E0A;&#x62C6;&#x51FA;&#x8FD9;&#x4E24;&#x5C42;&#x5DF2;&#x7ECF;&#x5DEE;&#x4E0D;&#x591A;</li><li>&#x753B;&#x51FA;&#x6838;&#x5FC3;&#x529F;&#x80FD;&#x7684;&#x4F9D;&#x8D56;&#x5904;&#x7406;&#x6D41;&#x7A0B;&#x56FE;</li><li>&#x67E5;&#x770B;&#x6BCF;&#x4E2A;&#x529F;&#x80FD;&#x7684;&#x6838;&#x5FC3;&#x7C7B;&#xFF0C;&#x641E;&#x6E05;&#x695A;&#x4E0D;&#x540C;&#x529F;&#x80FD;&#x7684;&#x6838;&#x5FC3;&#x7C7B;&#x7684;&#x4EA4;&#x4E92;&#x673A;&#x5236;&#x4EE5;&#x53CA;&#x5982;&#x4F55;&#x6784;&#x5EFA;&#x51FA;&#x8FD9;&#x4E2A;&#x6846;&#x67B6;&#x7684;&#x6838;&#x5FC3;&#x80FD;&#x529B;&#xFF0C;&#x8F93;&#x51FA;&#x6838;&#x5FC3;&#x6D41;&#x7A0B;&#x56FE;&#xFF08;&#x65F6;&#x5E8F;&#x56FE;&#x4E5F;&#x53EF;&#xFF09;</li><li>&#x4ECE;&#x6838;&#x5FC3;&#x7C7B;&#x51FA;&#x53D1;&#xFF0C;&#x67E5;&#x770B;&#x5176;&#x5B83;&#x652F;&#x6491;&#x7C7B;&#x7684;&#x4F5C;&#x7528;&#xFF0C;&#x5E76;&#x6784;&#x5EFA;&#x7C7B;&#x56FE;</li><li>&#x4ECE;&#x5E95;&#x5F80;&#x4E0A;&#x51FA;&#x53D1;&#xFF0C;&#x67E5;&#x770B;&#x6846;&#x67B6;&#x5E94;&#x7528;&#x7684;&#x8BBE;&#x8BA1;&#x6A21;&#x5F0F;&#x4EE5;&#x53CA;&#x4E3A;&#x4F55;&#x9700;&#x8981;&#x4F7F;&#x7528;&#x8FD9;&#x4E2A;&#x8BBE;&#x8BA1;&#x6A21;&#x5F0F;&#xFF0C;&#x5BF9;&#x4E8E;&#x6269;&#x5C55;&#x6027;&#x3001;&#x6613;&#x7528;&#x6027;&#x3001;&#x53EF;&#x8BFB;&#x6027;&#x7B49;&#x7684;&#x5F71;&#x54CD;&#x5728;&#x54EA;&#x91CC;</li><li>&#x603B;&#x7ED3;&#x6027;&#x6587;&#x6863;&#x8F93;&#x51FA;</li></ol><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;&amp;#x80CC;&amp;#x666F;&quot;&gt;&lt;a href=&quot;#&amp;#x80CC;&amp;#x666F;&quot; class=&quot;headerlink&quot; title=&quot;&amp;#x80CC;&amp;#x666F;&quot;&gt;&lt;/a&gt;&amp;#x80CC;&amp;#x666F;&lt;/h3&gt;&lt;p&gt;&amp;#x8FD9;&amp;#x51E
      
    
    </summary>
    
      <category term="Methodology" scheme="https://xuqiang.me/categories/Methodology/"/>
    
    
      <category term="analysis" scheme="https://xuqiang.me/tags/analysis/"/>
    
      <category term="opensource" scheme="https://xuqiang.me/tags/opensource/"/>
    
      <category term="structure" scheme="https://xuqiang.me/tags/structure/"/>
    
  </entry>
  
  <entry>
    <title>如何设计短域名系统</title>
    <link href="https://xuqiang.me/2019-12-14-how-to-design-short-domain-system.html"/>
    <id>https://xuqiang.me/2019-12-14-how-to-design-short-domain-system.html</id>
    <published>2019-12-14T15:08:43.000Z</published>
    <updated>2019-12-20T16:32:08.133Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x6574;&#x4F53;&#x65B9;&#x6CD5;&#x8BBA;&#x5B66;&#x4E60;&#x4E0E;&#x5C1D;&#x8BD5;</p><a id="more"></a><h3 id="&#x65B9;&#x6CD5;&#x8BBA;"><a href="#&#x65B9;&#x6CD5;&#x8BBA;" class="headerlink" title="&#x65B9;&#x6CD5;&#x8BBA;"></a>&#x65B9;&#x6CD5;&#x8BBA;</h3><p>&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x76EE;&#x7684; -&gt; &#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x76EE;&#x6807; -&gt; &#x56F4;&#x7ED5;&#x76EE;&#x6807;&#x7684;&#x6838;&#x5FC3;&#x8BBE;&#x8BA1; -&gt; &#x56F4;&#x7ED5;&#x6838;&#x5FC3;&#x8BBE;&#x8BA1;&#x5F62;&#x6210;&#x7684;&#x8BBE;&#x8BA1;&#x539F;&#x5219; -&gt; &#x5404;&#x5B50;&#x7CFB;&#x7EDF;</p><h4 id="&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x76EE;&#x7684;"><a href="#&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x76EE;&#x7684;" class="headerlink" title="&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x76EE;&#x7684;"></a>&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x76EE;&#x7684;</h4><ul><li>&#x8BBE;&#x8BA1;&#x4E00;&#x4E2A;&#x6613;&#x7528;&#x3001;&#x9AD8;&#x53EF;&#x7528;&#x3001;&#x53EF;&#x652F;&#x6301;&#x5927;&#x89C4;&#x6A21;&#x8BBF;&#x95EE;&#x7684;&#x77ED;&#x57DF;&#x540D;&#x7CFB;&#x7EDF;</li></ul><h4 id="&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x76EE;&#x6807;"><a href="#&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x76EE;&#x6807;" class="headerlink" title="&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x76EE;&#x6807;"></a>&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x7684;&#x76EE;&#x6807;</h4><ul><li>&#x652F;&#x6301;&#x77ED;&#x57DF;&#x540D;&#x9886;&#x57DF;TOP5&#x7684;&#x7F51;&#x7AD9;&#x89C4;&#x6A21;</li><li>&#x652F;&#x6301;99%&#x7684;&#x53EF;&#x7528;&#x6027;</li><li>&#x54CD;&#x5E94;&#x65F6;&#x95F4;&#x5728;100ms&#x4EE5;&#x5185;</li><li>&#x57DF;&#x540D;&#x957F;&#x5EA6;&#x9650;&#x5236;&#x5728;10&#x4E2A;&#x5B57;&#x7B26;&#x4EE5;&#x5185;</li></ul><h4 id="&#x56F4;&#x7ED5;&#x76EE;&#x6807;&#x7684;&#x6838;&#x5FC3;&#x8BBE;&#x8BA1;"><a href="#&#x56F4;&#x7ED5;&#x76EE;&#x6807;&#x7684;&#x6838;&#x5FC3;&#x8BBE;&#x8BA1;" class="headerlink" title="&#x56F4;&#x7ED5;&#x76EE;&#x6807;&#x7684;&#x6838;&#x5FC3;&#x8BBE;&#x8BA1;"></a>&#x56F4;&#x7ED5;&#x76EE;&#x6807;&#x7684;&#x6838;&#x5FC3;&#x8BBE;&#x8BA1;</h4><p>&#x5BF9;&#x4E0A;&#x8FF0;&#x7CFB;&#x7EDF;&#x76EE;&#x6807;&#x505A;&#x6280;&#x672F;&#x6027;&#x7684;&#x4E00;&#x4E2A;&#x62C6;&#x5206;</p><ul><li>&#x652F;&#x6301;&#x77ED;&#x57DF;&#x540D;&#x9886;&#x57DF;TOP5&#x7684;&#x7F51;&#x7AD9;&#x89C4;&#x6A21;<ul><li>&#x5168;&#x7403;&#x6392;&#x540D;&#x7B2C;&#x4E8C;&#x7684;Youtube&#x6708;&#x8BBF;&#x95EE;&#x91CF;&#xFF1A;284.4&#x4EBF;&#xFF08;&#x8FD1;6&#x4E2A;&#x6708;PV&#x6570;&#x636E;&#x91CF;&#xFF09; * 9.56 / 6 = 453.144&#x4EBF;</li><li>&#x6309;&#x7167;&#x4E8C;&#x516B;&#x539F;&#x5219;&#xFF0C;TOP5&#x7684;&#x6708;&#x6D41;&#x91CF;&#x5927;&#x6982;&#x5728;90.63&#x4EBF;&#x6B21;</li><li>&#x5047;&#x8BBE;15%&#x7684;&#x8BF7;&#x6C42;&#x8BBF;&#x95EE;&#x5230;&#x77ED;&#x57DF;&#x540D;&#x751F;&#x6210;&#x670D;&#x52A1;&#xFF0C;&#x751F;&#x6210;&#x77ED;&#x57DF;&#x540D;&#x6708;&#x8BBF;&#x95EE;&#x91CF;&#x7EA7;&#x522B;&#x5728;13.59&#x4EBF;&#x6B21;</li><li>&#x5047;&#x8BBE;30%&#x7684;&#x8BF7;&#x6C42;&#x8BBF;&#x95EE;&#x5230;&#x77ED;&#x57DF;&#x540D;&#x751F;&#x6210;&#x7684;&#x77ED;&#x8FDE;&#x63A5;&#x4E0A;&#xFF0C;&#x77ED;&#x57DF;&#x540D;&#x8F6C;&#x5316;&#x670D;&#x52A1;&#x6708;&#x8BBF;&#x95EE;&#x91CF;&#x7EA7;&#x522B;&#x5728;27.19&#x4EBF;</li><li>&#x751F;&#x6210;&#x77ED;&#x57DF;&#x540D;&#x670D;&#x52A1;&#x6309;&#x7167;&#x57DF;&#x540D;&#x5B58;&#x50A8;&#x7684;&#x91CF;&#x7EA7;&#x8BA1;&#x7B97;<ul><li>&#x5047;&#x8BBE;&#x6309;&#x6700;&#x957F;&#x957F;&#x5EA6;&#x5B58;&#x50A8;&#xFF0C;&#x5373;10&#x5B57;&#x7B26;&#xFF0C;&#x9700;&#x8981;&#x6708;&#x5B58;&#x50A8;&#x7684;key&#x91CF;&#x7EA7;&#x5728;10 <em>4 </em>13.59&#x4EBF; / 1024 / 1024 / 1024 = 50.63GB&#xFF1B;&#x5E74;&#x5B58;&#x50A8;&#x91CF;&#x7EA7;607.52GB</li><li>&#x5047;&#x8BBE;&#x8F6C;&#x53D1;&#x7F51;&#x5740;&#x957F;&#x5EA6;&#x5E73;&#x5747;&#x5728;100&#x5B57;&#x7B26;&#xFF0C;&#x9700;&#x8981;&#x6708;&#x5B58;&#x50A8;&#x7684;value&#x91CF;&#x7EA7;&#x5728;10 * 50.63GB = 506.3GB&#xFF1B;&#x5E74;&#x5B58;&#x50A8;&#x7EA7;6075.6GB</li></ul></li></ul></li><li>&#x652F;&#x6301;99.9%&#x7684;&#x53EF;&#x7528;&#x6027;<ul><li>&#x81EA;&#x7136;&#x5E74;&#x5185;&#x670D;&#x52A1;&#x4E2D;&#x65AD;&#x65F6;&#x957F;&#x4E0D;&#x80FD;&#x8D85;&#x8FC7;8.76&#x5C0F;&#x65F6;</li></ul></li><li>&#x54CD;&#x5E94;&#x65F6;&#x95F4;&#x5728;100ms&#x4EE5;&#x5185;<ul><li>&#x751F;&#x6210;&#x77ED;&#x57DF;&#x540D;&#x8BF7;&#x6C42;&#x4E3A;13.59&#x4EBF;&#x6B21;/&#x6708;&#xFF0C;TPS&#x5927;&#x6982;&#x4E3A;525</li><li>&#x77ED;&#x57DF;&#x540D;&#x4EE3;&#x7406;&#x8DF3;&#x8F6C;&#x8BF7;&#x6C42;&#x4E3A;27.19&#x4EBF;&#x6B21;/&#x6708;&#xFF0C;QPS&#x5927;&#x6982;&#x4E3A;1049</li></ul></li><li>&#x57DF;&#x540D;&#x957F;&#x5EA6;&#x9650;&#x5236;&#x5728;10&#x4E2A;&#x5B57;&#x7B26;&#x4EE5;&#x5185;<ul><li>&#x76EE;&#x524D;&#x4E92;&#x8054;&#x7F51;&#x5B58;&#x5728;40.1M&#x4E2A;&#x7F51;&#x7AD9;</li><li>10&#x4E2A;&#x5B57;&#x7B26;&#x6309;&#x7167;&#x5927;&#x5C0F;&#x5199;&#x6570;&#x5B57;&#x8BA1;&#x7B97;62^10 &gt;&gt; 40.1M</li></ul></li></ul><h4 id="&#x5404;&#x5B50;&#x7CFB;&#x7EDF;"><a href="#&#x5404;&#x5B50;&#x7CFB;&#x7EDF;" class="headerlink" title="&#x5404;&#x5B50;&#x7CFB;&#x7EDF;"></a>&#x5404;&#x5B50;&#x7CFB;&#x7EDF;</h4><p>&#x6839;&#x636E;&#x5355;&#x4E00;&#x804C;&#x8D23;&#x8BBE;&#x8BA1;&#x539F;&#x5219;&#xFF0C;&#x5212;&#x5206;&#x5B50;&#x7CFB;&#x7EDF;&#xFF1A;</p><ol><li>&#x77ED;&#x57DF;&#x540D;&#x751F;&#x6210;&#x670D;&#x52A1;&#xFF1A;&#x5C06;&#x957F;&#x94FE;&#x63A5;&#x8F6C;&#x4E3A;&#x77ED;&#x8FDE;&#x63A5;</li><li>&#x77ED;&#x57DF;&#x540D;&#x4EE3;&#x7406;&#x670D;&#x52A1;&#xFF1A;&#x6839;&#x636E;&#x77ED;&#x8FDE;&#x63A5;302&#x8DF3;&#x8F6C;&#x81F3;&#x76EE;&#x6807;&#x5730;&#x5740;</li></ol><h3 id="&#x5177;&#x4F53;&#x8BBE;&#x8BA1;"><a href="#&#x5177;&#x4F53;&#x8BBE;&#x8BA1;" class="headerlink" title="&#x5177;&#x4F53;&#x8BBE;&#x8BA1;"></a>&#x5177;&#x4F53;&#x8BBE;&#x8BA1;</h3><p>&#x56F4;&#x7ED5;&#x4E0A;&#x8FF0;&#x7684;&#x6838;&#x5FC3;&#x8BBE;&#x8BA1;&#xFF0C;&#x53EF;&#x4EE5;&#x9884;&#x77E5;&#x7684;&#x6311;&#x6218;&#x4E3B;&#x8981;&#x6709;&#x5982;&#x4E0B;&#x51E0;&#x70B9;&#xFF1A;</p><ol><li>5&#x5E74;&#x5185;hash&#x5B58;&#x50A8;&#x91CF;&#x7EA7;&#x5728;3TB&#xFF0C;&#x539F;&#x59CB;url&#x4FE1;&#x606F;&#x5B58;&#x50A8;&#x91CF;&#x7EA7;&#x5728;30TB&#x5DE6;&#x53F3;</li><li>&#x6BCF;&#x79D2;&#x603B;&#x8BF7;&#x6C42; 1600 &#x5DE6;&#x53F3;</li><li>99.9%&#x7684;&#x53EF;&#x7528;&#x6027;</li></ol><p>&#x63A5;&#x4E0B;&#x6765;&#x5BF9;&#x4E8E;3&#x4E2A;&#x9884;&#x77E5;&#x7684;&#x6311;&#x6218;&#x70B9;&#x505A;&#x5177;&#x4F53;&#x7684;&#x5206;&#x6790;&#x63A2;&#x8BA8;</p><h4 id="&#x5B58;&#x50A8;&#x95EE;&#x9898;"><a href="#&#x5B58;&#x50A8;&#x95EE;&#x9898;" class="headerlink" title="&#x5B58;&#x50A8;&#x95EE;&#x9898;"></a>&#x5B58;&#x50A8;&#x95EE;&#x9898;</h4><p>&#x5728;&#x4E0D;&#x8FDB;&#x884C;&#x4EFB;&#x4F55;&#x8F6C;&#x5316;&#x7B97;&#x6CD5;&#x4EE5;&#x53CA;&#x6570;&#x636E;&#x538B;&#x7F29;&#x4E4B;&#x524D;&#xFF0C;&#x6570;&#x636E;&#x7684;&#x5B58;&#x50A8;&#x91CF;&#x7EA7;&#x662F;&#x975E;&#x5E38;&#x5927;&#x7684;&#x3002;<br>&#x8FD9;&#x4F1A;&#x9020;&#x6210;&#x4E24;&#x4E2A;&#x5F71;&#x54CD;&#xFF1A;</p><ol><li>&#x65E0;&#x6CD5;&#x5FEB;&#x901F;&#x7D22;&#x5F15;&#xFF0C;&#x5373;&#x4F7F;&#x4F7F;&#x7528;KV&#x6570;&#x636E;&#x5E93;&#xFF0C;&#x4E5F;&#x9700;&#x8981;&#x627E;&#x5230;&#x8FD9;&#x4E2A;KEY&#x7684;&#x4F4D;&#x7F6E;</li><li>&#x8FC7;&#x4E8E;&#x5E9E;&#x5927;&#x7684;&#x6570;&#x636E;&#x5E93;&#x5BF9;&#x4E8E;&#x78C1;&#x76D8;&#x5B58;&#x5728;&#x4E00;&#x5B9A;&#x7684;&#x6C34;&#x5E73;&#x6269;&#x5C55;&#x538B;&#x529B;</li></ol><p>&#x6240;&#x4EE5;&#xFF0C;&#x9700;&#x8981;&#x4ECE;&#x4EE5;&#x4E0B;&#x51E0;&#x4E2A;&#x70B9;&#x8003;&#x8651;&#x4E0A;&#x8FF0;&#x4E24;&#x4E2A;&#x95EE;&#x9898;&#xFF1A;</p><ol><li>&#x5982;&#x4F55;&#x6784;&#x5EFA;&#x5FEB;&#x901F;&#x67E5;&#x8BE2;&#x7684;&#x7D22;&#x5F15;&#x7ED3;&#x6784;&#xFF0C;&#x5C3D;&#x53EF;&#x80FD;&#x5728;&#x8F83;&#x5C11;&#x7684;&#x65F6;&#x95F4;&#x590D;&#x6742;&#x5EA6;&#x4E0B;&#x83B7;&#x53D6;&#x7ED3;&#x679C;<ul><li>&#x73B0;&#x6709;&#x7684;&#x4E0D;&#x7BA1;&#x662F;&#x5173;&#x7CFB;&#x578B;&#x6570;&#x636E;&#x5E93;MySQL&#xFF0C;&#x8FD8;&#x662F;NoSQL&#x7C7B;&#x578B;&#x7684;MongoDB&#x3001;HBase&#x7B49;&#xFF0C;&#x5BF9;&#x4E8E;&#x952E;&#x7684;&#x67E5;&#x8BE2;&#x8FD8;&#x662F;&#x6BD4;&#x8F83;&#x5FEB;&#x7684;&#xFF0C;&#x65F6;&#x95F4;&#x590D;&#x6742;&#x5EA6;&#x5728;O(logn)&#x7EA7;&#x522B;&#x3002;<br>&#x6240;&#x4EE5;&#x5728;&#x7D22;&#x5F15;&#x67E5;&#x8BE2;&#x4E0A;&#xFF0C;&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x4F7F;&#x7528;&#x73B0;&#x6709;&#x7684;&#x5B58;&#x50A8;&#x6570;&#x636E;&#x5E93;&#x3002;</li></ul></li><li>&#x5982;&#x4F55;&#x5904;&#x7406;&#x6570;&#x636E;&#x5B58;&#x50A8;&#x7684;&#x538B;&#x7F29;&#xFF0C;&#x51CF;&#x5C11;&#x5B58;&#x50A8;&#x7684;&#x538B;&#x529B;<ul><li>&#x5728;&#x6570;&#x636E;&#x5B58;&#x50A8;&#x5C42;&#x9762;&#x53EF;&#x4EE5;&#x8003;&#x8651;&#x4F7F;&#x7528;&#x53D8;&#x957F;&#x5B57;&#x6BB5;&#xFF0C;&#x800C;&#x4E0D;&#x662F;&#x56FA;&#x957F;&#x5B57;&#x6BB5;&#x51CF;&#x5C11;&#x6570;&#x636E;&#x5360;&#x7528;</li></ul></li><li>&#x5982;&#x4F55;&#x5728;&#x78C1;&#x76D8;&#x5BB9;&#x91CF;&#x4E0D;&#x8DB3;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#xFF0C;&#x8FBE;&#x5230;&#x5E73;&#x6ED1;&#x6269;&#x5BB9;&#x7684;&#x6548;&#x679C;&#xFF0C;&#x800C;&#x4E0D;&#x4F1A;&#x5F71;&#x54CD;&#x73B0;&#x6709;&#x7684;&#x7CFB;&#x7EDF;<ul><li>&#x4F7F;&#x7528;&#x73B0;&#x6210;&#x7684;&#x53EF;&#x6269;&#x5BB9;&#x6570;&#x636E;&#x5B58;&#x50A8;&#x6765;&#x5B9E;&#x73B0;&#x6548;&#x679C;</li><li>&#x81EA;&#x5DF1;&#x5B9E;&#x73B0;&#x5206;&#x5E03;&#x5F0F;&#x5B58;&#x50A8;&#xFF0C;&#x4F7F;&#x7528;&#x4E00;&#x81F4;&#x6027;hash&#x7B97;&#x6CD5;&#x6765;&#x5206;&#x53D1;&#xFF1B;&#x4F46;&#x662F;&#x5982;&#x679C;&#x65B0;&#x589E;&#x4E86;&#x4E00;&#x4E2A;&#x7269;&#x7406;&#x5B58;&#x50A8;&#x8282;&#x70B9;&#xFF0C;&#x9700;&#x8981;&#x8FDB;&#x884C;&#x6570;&#x636E;&#x91CD;&#x65B0;&#x5206;&#x914D;&#x64CD;&#x4F5C;</li></ul></li></ol><h4 id="&#x9AD8;&#x5E76;&#x53D1;&#x95EE;&#x9898;"><a href="#&#x9AD8;&#x5E76;&#x53D1;&#x95EE;&#x9898;" class="headerlink" title="&#x9AD8;&#x5E76;&#x53D1;&#x95EE;&#x9898;"></a>&#x9AD8;&#x5E76;&#x53D1;&#x95EE;&#x9898;</h4><p>&#x6BCF;&#x79D2;&#x603B;&#x8BF7;&#x6C42;1600&#x5DE6;&#x53F3;&#xFF0C;&#x5176;&#x4E2D;&#x5199;&#x8BF7;&#x6C42;525&#xFF0C;&#x8BFB;&#x8BF7;&#x6C42;1049&#xFF1B;&#x53EF;&#x4EE5;&#x786E;&#x8BA4;&#x662F;&#x8BFB;&#x591A;&#x5199;&#x5C11;&#x7684;&#x4E1A;&#x52A1;&#x573A;&#x666F;&#xFF0C;&#x53EF;&#x4EE5;&#x4ECE;&#x4EE5;&#x4E0B;&#x56DB;&#x4E2A;&#x65B9;&#x9762;&#x4F18;&#x5316;&#xFF1A;</p><ol><li>&#x51CF;&#x5C11;&#x4E0A;&#x6E38;&#x8BF7;&#x6C42;&#x6570;<ul><li>&#x4F7F;&#x7528;&#x5E03;&#x9686;&#x8FC7;&#x6EE4;&#x5668;&#xFF0C;&#x4E0D;&#x5B58;&#x5728;&#x7684;&#x5FC5;&#x5B9A;&#x4E0D;&#x5B58;&#x5728;<ul><li>&#x6309;&#x7167;5&#x5E74;hash&#x5B58;&#x50A8;&#x8BB0;&#x5F55;&#x6570;&#x6765;&#x8BA1;&#x7B97;&#xFF0C;&#x9700;&#x8981;&#x5B58;&#x50A8;480&#x4EBF;&#x7684;key</li><li>&#x5E03;&#x9686;&#x8FC7;&#x6EE4;&#x5668;1%&#x8BEF;&#x5DEE;&#x7387;&#xFF0C;&#x4E00;&#x4E2A;key&#x5927;&#x6982;&#x9700;&#x8981;9.6bits&#x7A7A;&#x95F4;&#xFF0C;480&#x4EBF;&#x7684;key&#x5927;&#x6982;&#x9700;&#x8981;53GB&#x7684;&#x5185;&#x5B58;&#x91CF;</li></ul></li></ul></li><li>&#x8DEF;&#x7531;&#x5206;&#x53D1;&#xFF0C;&#x4E14;&#x5BF9;&#x5E94;&#x8BFB;&#x670D;&#x52A1;&#x505A;&#x7F13;&#x5B58;&#x4FDD;&#x8BC1;<ul><li>&#x5728;&#x7F51;&#x5173;&#x5C42;&#x5C06;key&#x505A;&#x4E00;&#x5C42;hash&#xFF0C;&#x5206;&#x6563;&#x5230;&#x4E00;&#x81F4;&#x6027;hash&#x73AF;&#x4E0A;</li><li>&#x6BCF;&#x4E2A;&#x77ED;&#x57DF;&#x540D;&#x4EE3;&#x7406;&#x8F6C;&#x53D1;&#x670D;&#x52A1;&#x5668;&#xFF0C;&#x90FD;&#x6709;&#x4E00;&#x4E2A;LRU&#x7684;&#x672C;&#x5730;&#x7F13;&#x5B58;</li></ul></li><li>&#x62BD;&#x79BB;&#x70ED;&#x70B9;&#x6570;&#x636E;&#xFF0C;&#x5BF9;&#x4E0D;&#x540C;key&#x7684;&#x8BBF;&#x95EE;&#x505A;&#x5206;&#x503C;&#x7EDF;&#x8BA1;&#xFF0C;&#x9AD8;&#x5206;&#x503C;&#x6570;&#x636E;&#x5230;&#x8FBE;&#x4E00;&#x4E2A;&#x9608;&#x503C;&#x5B58;&#x5165;&#x96C6;&#x4E2D;&#x5F0F;&#x7F13;&#x5B58;<ul><li>&#x77ED;&#x57DF;&#x540D;&#x4EE3;&#x7406;&#x8F6C;&#x53D1;&#x670D;&#x52A1;&#x5668;&#x542F;&#x52A8;&#x7684;&#x65F6;&#x5019;&#x9884;&#x52A0;&#x8F7D;&#x70ED;&#x70B9;&#x6570;&#x636E;&#x81F3;&#x672C;&#x5730;&#x7F13;&#x5B58;</li><li>&#x8BBF;&#x95EE;&#x5B8C;&#x6210;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x5982;&#x679C;&#x67D0;&#x4E2A;key&#x8FBE;&#x5230;&#x4E00;&#x4E2A;&#x9608;&#x503C;&#x540E;&#xFF0C;&#x5219;&#x5F02;&#x6B65;&#x5C06;&#x8BE5;&#x503C;&#x5B58;&#x5165;&#x672C;&#x5730;&#x7F13;&#x5B58;&#xFF0C;&#x5E76;&#x5E7F;&#x64AD;&#x5B8C;&#x6210;&#x540E;&#xFF0C;&#x5B58;&#x5165;&#x81F3;&#x96C6;&#x4E2D;&#x5F0F;&#x7F13;&#x5B58;&#x5185;&#xFF1B;&#x5B58;&#x50A8;&#x5931;&#x8D25;&#x5219;&#x6700;&#x591A;3&#x6B21;&#x91CD;&#x8BD5;</li></ul></li><li>&#x5B58;&#x50A8;&#x5C42;&#x9762;&#x8BFB;&#x5199;&#x5206;&#x79BB;</li></ol><h4 id="&#x9AD8;&#x53EF;&#x7528;&#x95EE;&#x9898;"><a href="#&#x9AD8;&#x53EF;&#x7528;&#x95EE;&#x9898;" class="headerlink" title="&#x9AD8;&#x53EF;&#x7528;&#x95EE;&#x9898;"></a>&#x9AD8;&#x53EF;&#x7528;&#x95EE;&#x9898;</h4><p>&#x53EF;&#x7528;&#x6027;&#x4E3B;&#x8981;&#x4F53;&#x73B0;&#x5728;&#x4EE5;&#x4E0B;&#x51E0;&#x4E2A;&#x65B9;&#x9762;&#xFF1A;</p><ol><li>&#x670D;&#x52A1;&#x7684;&#x53EF;&#x7528;&#x6027;<ul><li>&#x6CE8;&#x518C;&#x4E2D;&#x5FC3;&#x672C;&#x8EAB;&#x4F7F;&#x7528;&#x591A;&#x8282;&#x70B9;&#x4E3B;&#x5907;&#x7B56;&#x7565;&#xFF0C;&#x4FDD;&#x8BC1;&#x81EA;&#x8EAB;&#x9AD8;&#x53EF;&#x7528;</li><li>&#x6CE8;&#x518C;&#x4E2D;&#x5FC3;&#x7EF4;&#x62A4;&#x670D;&#x52A1;&#x7684;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#xFF0C;&#x670D;&#x52A1;&#x8C03;&#x7528;&#x901A;&#x8FC7;&#x6CE8;&#x518C;&#x4E2D;&#x5FC3;&#x8C03;&#x7528;&#x76EE;&#x6807;&#x670D;&#x52A1;&#x5668;&#xFF0C;&#x53EF;&#x4EE5;&#x9009;&#x62E9;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x7B56;&#x7565;&#x4E3A;<code>WeightedResponseTimeRule</code></li></ul></li><li>&#x6570;&#x636E;&#x5B58;&#x50A8;&#x53EF;&#x7528;&#x6027;<ul><li>&#x4E3B;&#x4ECE;&#x5907;&#x4EFD;&#x673A;&#x5236;</li></ul></li><li>&#x6570;&#x636E;&#x672C;&#x8EAB;&#x53EF;&#x7528;&#x6027;<ul><li>&#x5F02;&#x673A;replica&#x673A;&#x5236;&#xFF0C;&#x4FDD;&#x8BC1;&#x6570;&#x636E;&#x7684;&#x53EF;&#x6062;&#x590D;&#x6027;</li></ul></li></ol><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;系统设计的整体方法论学习与尝试&lt;/p&gt;
    
    </summary>
    
      <category term="系统设计" scheme="https://xuqiang.me/categories/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/"/>
    
    
      <category term="系统设计" scheme="https://xuqiang.me/tags/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/"/>
    
      <category term="短域名" scheme="https://xuqiang.me/tags/%E7%9F%AD%E5%9F%9F%E5%90%8D/"/>
    
  </entry>
  
  <entry>
    <title>Linux启动过程分析详解</title>
    <link href="https://xuqiang.me/linux-startup-analyize.html"/>
    <id>https://xuqiang.me/linux-startup-analyize.html</id>
    <published>2019-10-04T06:04:42.000Z</published>
    <updated>2019-10-04T08:53:45.748Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x4E00;&#x76F4;&#x60F3;&#x8981;&#x81EA;&#x5DF1;&#x505A;&#x51FA;&#x4E00;&#x4E2A;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#xFF0C;&#x56E0;&#x6B64;&#x5BF9;&#x4E8E;&#x73B0;&#x6709;linux&#x9700;&#x8981;&#x6709;&#x4E2A;&#x8BE6;&#x7EC6;&#x7684;&#x4E86;&#x89E3;&#xFF0C;&#x77E5;&#x9053;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#x5982;&#x4F55;&#x5B9E;&#x73B0;&#x6240;&#x6709;&#x7684;&#x8FC7;&#x7A0B;&#x3002;&#x56E0;&#x6B64;&#xFF0C;&#x5728;&#x8FD9;&#x7BC7;&#x6587;&#x7AE0;&#x4E2D;&#x8BB0;&#x5F55;&#x4E0B;linux&#x7684;&#x8BE6;&#x7EC6;&#x542F;&#x52A8;&#x8FC7;&#x7A0B;&#x3002;</p><p>&#x672C;&#x7BC7;&#x6253;&#x7B97;&#x4ECE;&#x4E09;&#x4E2A;&#x90E8;&#x5206;&#x8BB2;&#x89E3;Linux&#x542F;&#x52A8;&#x7684;&#x8FC7;&#x7A0B;&#xFF1A;</p><ol><li>BIOS&#x9636;&#x6BB5;</li><li>BootLoader&#x9636;&#x6BB5;</li><li>&#x5185;&#x6838;&#x542F;&#x52A8;&#x9636;&#x6BB5;</li></ol><p>&#x672C;&#x6587;&#x524D;&#x63D0;&#xFF1A;&#x975E;UEFI&#x6A21;&#x5F0F;</p><a id="more"></a><h3 id="BIOS&#x9636;&#x6BB5;"><a href="#BIOS&#x9636;&#x6BB5;" class="headerlink" title="BIOS&#x9636;&#x6BB5;"></a>BIOS&#x9636;&#x6BB5;</h3><p>&#x5F53;&#x8BA1;&#x7B97;&#x673A;&#x542F;&#x52A8;&#x7535;&#x6E90;&#xFF0C;CPU&#x9700;&#x8981;&#x6267;&#x884C;&#x7B2C;&#x4E00;&#x6761;&#x6307;&#x4EE4;&#xFF0C;&#x8FD9;&#x6761;&#x6307;&#x4EE4;&#x53C8;&#x4ECE;&#x4F55;&#x800C;&#x6765;&#xFF1F;</p><p>&#x8BA1;&#x7B97;&#x673A;&#x7684;&#x5185;&#x5B58;&#x4F1A;&#x5C06;&#x5185;&#x5B58;&#x5212;&#x5206;&#x4E3A;&#x591A;&#x4E2A;&#x533A;&#xFF0C;&#x6BCF;&#x4E2A;&#x533A;&#x90FD;&#x6709;&#x4E0D;&#x540C;&#x7684;&#x529F;&#x80FD;&#xFF0C;&#x751A;&#x81F3;&#x76F4;&#x63A5;&#x6620;&#x5C04;&#x5230;&#x786C;&#x4EF6;&#x3002;&#x5982;&#x4E0B;&#x56FE;&#x4E3A;&#x5185;&#x5B58;&#x5212;&#x5206;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/062834.jpg" alt="&#x5185;&#x5B58;&#x5212;&#x5206;"></p><p>&#x4E0A;&#x56FE;&#x4E2D;&#xFF0C;0xF0000 ~ 0xFFFFF &#x4E3A;ROM&#x533A;&#xFF0C;&#x76F4;&#x63A5;&#x6620;&#x5C04;&#x4E3A;BIOS&#x82AF;&#x7247;&#x5B58;&#x50A8;&#x533A;&#x3002;&#x5F53;&#x7535;&#x8111;&#x542F;&#x52A8;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x76F8;&#x5173;&#x7684;&#x5BC4;&#x5B58;&#x5668;&#x5C06;&#x4F1A;&#x88AB;&#x521D;&#x59CB;&#x5316;&#xFF0C;&#x8FD9;&#x8FB9;&#x91CD;&#x70B9;&#x5173;&#x6CE8;&#x6BB5;&#x5BC4;&#x5B58;&#x5668;CS&#x4EE5;&#x53CA;&#x6307;&#x4EE4;&#x6307;&#x9488;&#x5BC4;&#x5B58;&#x5668;IP&#x3002;CS&#x5C06;&#x4F1A;&#x91CD;&#x7F6E;&#x4E3A;0xF000&#xFF0C;IP&#x5C06;&#x4F1A;&#x91CD;&#x7F6E;&#x4E3A;0x0000&#xFF1B;CS:IP&#x6307;&#x5411;&#x7684;&#x5C31;&#x662F;&#x7B2C;&#x4E00;&#x6761;&#x6307;&#x4EE4;&#x7684;&#x5730;&#x5740;&#xFF1A;0xF0000&#x3002;&#x800C;&#x4ECE;&#x4E0A;&#x56FE;&#x53EF;&#x4EE5;&#x77E5;&#x6653;&#xFF0C;&#x8FD9;&#x4E2A;&#x5730;&#x5740;&#x5BF9;&#x5E94;&#x7684;&#x5C31;&#x662F;ROM&#x533A;&#x3002;</p><p>CPU&#x5F00;&#x59CB;&#x6267;&#x884C;ROM&#x533A;&#x7684;&#x6307;&#x4EE4;&#xFF0C;&#x7531;&#x4E8E;&#x8FD9;&#x5757;&#x533A;&#x57DF;&#x53EA;&#x6709;16&#x5B57;&#x8282;&#x7684;&#x5927;&#x5C0F;&#xFF0C;&#x6240;&#x4EE5;&#x4E0D;&#x4F1A;&#x653E;&#x7F6E;&#x592A;&#x8FC7;&#x590D;&#x6742;&#x7684;&#x7A0B;&#x5E8F;&#xFF0C;&#x4E00;&#x822C;&#x53EA;&#x6709;&#x4E00;&#x6761;JMP&#x6307;&#x4EE4;&#xFF1B;&#x8FD9;&#x6761;&#x6307;&#x4EE4;&#x6307;&#x5411;&#x7684;&#x662F;&#x4F4E;&#x5730;&#x5740;&#x7A7A;&#x95F4;&#xFF0C;&#x5E76;&#x5C06;BIOS&#x7A0B;&#x5E8F;&#x8F7D;&#x5165;&#x5230;RAM&#x7A7A;&#x95F4;&#x6267;&#x884C;&#x3002;&#x4E4B;&#x540E;&#x5F00;&#x59CB;&#x6267;&#x884C;&#x521D;&#x59CB;&#x5316;&#x8FC7;&#x7A0B;&#xFF0C;&#x5305;&#x62EC;&#x4E2D;&#x65AD;&#x5411;&#x91CF;&#x8868;&#x3001;&#x4E2D;&#x65AD;&#x670D;&#x52A1;&#xFF08;&#x5BF9;&#x4E8E;&#x952E;&#x76D8;&#x3001;&#x9F20;&#x6807;&#x7B49;&#x4E2D;&#x65AD;&#x4FE1;&#x53F7;&#x7684;&#x54CD;&#x5E94;&#x4EE5;&#x53CA;&#x5904;&#x7406;&#xFF09;&#x4EE5;&#x53CA;&#x786C;&#x4EF6;&#x5065;&#x5EB7;&#x81EA;&#x68C0;&#x3002;</p><p>&#x5982;&#x4E0B;&#x56FE;&#x63CF;&#x8FF0;&#x4E86;&#x6574;&#x4E2A;BIOS&#x542F;&#x52A8;&#x8FC7;&#x7A0B;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/070037.jpg" alt="BIOS&#x542F;&#x52A8;&#x8FC7;&#x7A0B;"></p><p>&#x4E0A;&#x56FE;&#x4E2D;&#x7684;&#x6D41;&#x7A0B;&#x9700;&#x8981;&#x63D0;&#x4E00;&#x5634;&#x7684;&#x662F;&#x5728;&#x6309;&#x4E0B;&#x3010;DEL&#x3011;&#x952E;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x4F1A;&#x8FDB;&#x884C;&#x4E2D;&#x65AD;&#x5904;&#x7406;&#xFF0C;&#x89E3;&#x538B;Setup&#x6A21;&#x5757;&#x3002;&#x8FD9;&#x4E2A;&#x6A21;&#x5757;&#x662F;&#x4E00;&#x4E2A;BIOS&#x8BBE;&#x7F6E;&#x5F15;&#x5BFC;&#x754C;&#x9762;&#x7A0B;&#x5E8F;&#xFF0C;&#x5728;BIOS&#x8BBE;&#x7F6E;&#x4E2D;&#x53EF;&#x4EE5;&#x8BBE;&#x7F6E;&#x542F;&#x52A8;&#x4ECB;&#x8D28;&#x4EE5;&#x53CA;&#x4ECB;&#x8D28;&#x7684;&#x542F;&#x52A8;&#x987A;&#x5E8F;&#x3001;&#x786C;&#x4EF6;&#x76F8;&#x5173;&#x7684;&#x4E00;&#x4E9B;&#x914D;&#x7F6E;&#x7B49;&#x7B49;&#x3002;&#x800C;&#x7531;&#x4E8E;BIOS&#x82AF;&#x7247;&#x662F;ROM&#x82AF;&#x7247;&#xFF0C;&#x4E0D;&#x5B58;&#x5728;&#x5B58;&#x50A8;&#x7684;&#x80FD;&#x529B;&#xFF0C;&#x6240;&#x4EE5;&#x8BA1;&#x7B97;&#x673A;&#x4E13;&#x95E8;&#x51C6;&#x5907;&#x4E86;&#x4E00;&#x4E2A;RAM&#x4ECB;&#x8D28;&#x7528;&#x4E8E;&#x5B58;&#x50A8;&#x914D;&#x7F6E;&#xFF0C;&#x8FD9;&#x4E2A;RAM&#x540D;&#x4E3A;CMOS&#x3002;&#x4E00;&#x822C;&#x6211;&#x4EEC;&#x7ECF;&#x5E38;&#x542C;&#x5230;&#x5176;&#x4ED6;&#x4EBA;&#x8BF4;&#x4EC0;&#x4E48;CMOS&#x653E;&#x7535;&#x5904;&#x7406;&#xFF0C;&#x5176;&#x5B9E;&#x5C31;&#x662F;&#x4E3A;&#x4E86;&#x8BA9;RAM&#x80FD;&#x591F;&#x957F;&#x671F;&#x4FDD;&#x5B58;&#x914D;&#x7F6E;&#xFF0C;&#x4F1A;&#x6709;&#x4E00;&#x4E2A;&#x4E13;&#x95E8;&#x7684;&#x7535;&#x6C60;&#x7528;&#x4E8E;&#x5BF9;CMOS&#x4F9B;&#x7535;&#xFF0C;&#x8FD9;&#x6837;&#x5373;&#x4FBF;&#x662F;&#x5728;&#x8BA1;&#x7B97;&#x673A;&#x65AD;&#x70B9;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#xFF0C;BIOS&#x7684;&#x8BBE;&#x7F6E;&#x4E5F;&#x4E0D;&#x4F1A;&#x4E22;&#x5931;&#xFF1B;&#x800C;&#x653E;&#x7535;&#x7684;&#x64CD;&#x4F5C;&#xFF0C;&#x5C31;&#x662F;&#x8BA9;CMOS&#x65AD;&#x7535;&#xFF0C;&#x5C06;&#x914D;&#x7F6E;&#x56DE;&#x590D;&#x5230;&#x521D;&#x59CB;&#x72B6;&#x6001;&#x3002;</p><p>&#x81EA;&#x6B64;&#xFF0C;BIOS&#x9636;&#x6BB5;&#x7ED3;&#x675F;&#x3002;</p><h3 id="BootLoader&#x9636;&#x6BB5;"><a href="#BootLoader&#x9636;&#x6BB5;" class="headerlink" title="BootLoader&#x9636;&#x6BB5;"></a>BootLoader&#x9636;&#x6BB5;</h3><p>&#x5728;BIOS&#x5728;&#x6267;&#x884C;&#x5B8C;&#x521D;&#x59CB;&#x5316;&#x5DE5;&#x4F5C;&#x540E;&#xFF0C;&#x6700;&#x7EC8;&#x7684;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#x53C8;&#x662F;&#x5982;&#x4F55;&#x88AB;&#x53D1;&#x73B0;&#x7684;&#xFF1F;</p><p>BIOS&#x7A0B;&#x5E8F;&#x5728;&#x5B8C;&#x6210;&#x786C;&#x4EF6;&#x81EA;&#x68C0;&#x4E4B;&#x540E;&#xFF0C;&#x5C31;&#x9700;&#x8981;&#x67E5;&#x8BE2;&#x4ECE;&#x542F;&#x52A8;&#x4ECB;&#x8D28;&#x4E2D;&#x67E5;&#x8BE2;&#x53EF;&#x5F15;&#x5BFC;&#x5206;&#x533A;&#x4E86;&#xFF0C;&#x800C;&#x5F15;&#x5BFC;&#x5206;&#x533A;&#x7684;&#x4F5C;&#x7528;&#x5C31;&#x662F;&#x7528;&#x6765;&#x8F7D;&#x5165;&#x6700;&#x7EC8;&#x7684;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#x3002;</p><p>&#x524D;&#x4E00;&#x8282;&#x5DF2;&#x7ECF;&#x8BB2;&#x8FC7;CMOS&#xFF0C;&#x4E5F;&#x77E5;&#x9053;CMOS&#x7528;&#x4E8E;&#x4FDD;&#x5B58;BIOS&#x914D;&#x7F6E;&#xFF0C;&#x5176;&#x4E2D;&#x5C31;&#x5305;&#x62EC;&#x4E86;&#x542F;&#x52A8;&#x4ECB;&#x8D28;&#x7684;&#x914D;&#x7F6E;&#x4EE5;&#x53CA;&#x987A;&#x5E8F;&#x8BBE;&#x7F6E;&#x3002;BIOS&#x7A0B;&#x5E8F;&#x4E4B;&#x540E;&#x5C31;&#x4F1A;&#x6309;&#x7167;&#x987A;&#x5E8F;&#x904D;&#x5386;&#x542F;&#x52A8;&#x4ECB;&#x8D28;&#xFF0C;&#x77E5;&#x9053;&#x53D1;&#x73B0;&#x53EF;&#x5F15;&#x5BFC;&#x5206;&#x533A;&#xFF08;MBR&#xFF09;&#xFF1B;&#x800C;MBR&#x5982;&#x4F55;&#x53D1;&#x73B0;&#x5462;&#xFF1F;&#x5728;&#x8F7D;&#x5165;&#x6BCF;&#x4E2A;&#x4ECB;&#x8D28;&#x7B2C;&#x4E00;&#x4E2A;&#x6247;&#x533A;&#xFF08;512&#x5B57;&#x8282;&#xFF09;&#x540E;&#xFF0C;&#x4F1A;&#x5C06;&#x8FD9;&#x6BB5;&#x5185;&#x5BB9;&#x9632;&#x6B62;&#x5728;&#x5185;&#x5B58;&#x4E0A;&#x7684;0x00000-0x7C00&#x533A;&#x57DF;&#xFF0C;&#x5E76;&#x5224;&#x65AD;&#x8FD9;&#x6BB5;&#x5185;&#x5BB9;&#x662F;&#x5426;&#x4EE5;AA55&#x8FD9;&#x4E24;&#x4E2A;&#x5B57;&#x8282;&#x7ED3;&#x675F;&#xFF1B;&#x5982;&#x679C;&#x662F;&#xFF0C;&#x5219;&#x8BE5;&#x4ECB;&#x8D28;&#x4E3A;&#x542F;&#x52A8;&#x4ECB;&#x8D28;&#xFF1B;&#x5426;&#x5219;&#xFF0C;&#x7EE7;&#x7EED;&#x67E5;&#x770B;&#x4E0B;&#x4E00;&#x4E2A;&#x4ECB;&#x8D28;&#x3002;</p><p>&#x53EF;&#x4EE5;&#x770B;&#x4E0B;&#x4E0B;&#x56FE;&#x7684;MBR&#x7684;&#x5F15;&#x5BFC;&#x5206;&#x533A;&#x7ED3;&#x6784;&#x56FE;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/071730.jpg" alt="MBR&#x5206;&#x533A;&#x7ED3;&#x6784;"></p><p>MBR&#x5206;&#x533A;&#x4E3B;&#x8981;&#x5206;&#x4E3A;&#x4E09;&#x4E2A;&#x5757;&#xFF1A;</p><ol><li>&#x4EE3;&#x7801;&#x5757;&#xFF1A;446&#x5B57;&#x8282;&#xFF0C;&#x4E3B;&#x8981;&#x7528;&#x4E8E;&#x5B58;&#x50A8;&#x53EF;&#x6267;&#x884C;&#x4EE3;&#x7801;&#x4EE5;&#x53CA;&#x9519;&#x8BEF;&#x6D88;&#x606F;&#x6587;&#x672C;</li><li>&#x5206;&#x533A;&#x8868;&#xFF1A;64&#x5B57;&#x8282;&#xFF0C;&#x6BCF;&#x4E2A;&#x5206;&#x533A;&#x5360;&#x7528;16&#x5B57;&#x8282;&#xFF0C;&#x6240;&#x4EE5;MBR&#x6700;&#x591A;&#x53EF;&#x4EE5;&#x5212;&#x5206;4&#x4E2A;&#x5206;&#x533A;&#xFF1B;&#x800C;&#x4E3A;&#x4E86;&#x7A81;&#x7834;&#x8FD9;&#x4E2A;&#x9650;&#x5236;&#xFF0C;MBR&#x5C06;&#x6700;&#x540E;&#x4E00;&#x4E2A;&#x5206;&#x533A;&#x5B9A;&#x4E49;&#x4E3A;&#x6269;&#x5C55;&#x5206;&#x533A;&#xFF0C;&#x7136;&#x540E;&#x5728;&#x6269;&#x5C55;&#x5206;&#x533A;&#x5185;&#x53EF;&#x4EE5;&#x5212;&#x5206;&#x903B;&#x8F91;&#x5206;&#x533A;</li><li>&#x7ED3;&#x675F;&#x7B26;&#xFF1A;2&#x5B57;&#x8282;</li></ol><p>&#x5728;&#x627E;&#x5230;MBR&#x4E4B;&#x540E;&#xFF0C;&#x4F1A;&#x52A0;&#x8F7D;&#x4EE3;&#x7801;&#x5757;&#x7684;&#x4EE3;&#x7801;&#xFF1B;&#x8FD9;&#x6BB5;&#x4EE3;&#x7801;&#x5C31;&#x662F;BootLoader&#xFF0C;&#x5373;GRUB&#x7684;&#x6700;&#x5C0F;&#x53EF;&#x6267;&#x884C;&#x7A0B;&#x5E8F;&#x3002;&#x4E3A;&#x4EC0;&#x4E48;&#x53EA;&#x88C5;&#x5728;&#x6700;&#x5C0F;&#x53EF;&#x6267;&#x884C;&#x7A0B;&#x5E8F;&#xFF0C;&#x4E3B;&#x8981;&#x539F;&#x56E0;&#x8FD8;&#x662F;&#x7531;&#x4E8E;MBR&#x7684;&#x53EF;&#x5BB9;&#x7EB3;&#x7A7A;&#x95F4;&#x8FC7;&#x4E8E;&#x5C0F;&#xFF0C;&#x8FD9;&#x6BB5;&#x7A0B;&#x5E8F;&#x4F1A;&#x52A0;&#x8F7D;&#x5B8C;&#x6574;&#x7684;GRUB&#x7A0B;&#x5E8F;&#x3002;</p><h4 id="GRUB"><a href="#GRUB" class="headerlink" title="GRUB"></a>GRUB</h4><p>GRUB&#xFF0C;GRand Unified Bootloader&#x3002;&#x5B83;&#x662F;&#x4E00;&#x4E2A;&#x591A;&#x91CD;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#x542F;&#x52A8;&#x7BA1;&#x7406;&#x5668;&#xFF0C;&#x7528;&#x6765;&#x5F15;&#x5BFC;&#x4E0D;&#x540C;&#x7CFB;&#x7EDF;&#xFF0C;&#x5982;windows&#xFF0C;linux&#x3002;</p><p>&#x5728;&#x542F;&#x52A8;BootLoader&#x4E4B;&#x540E;&#xFF0C;GRUB&#x6700;&#x5C0F;&#x6267;&#x884C;&#x7A0B;&#x5E8F;&#xFF08;boot.img&#xFF09;&#x4F1A;&#x8F7D;&#x5165;MBR&#x5206;&#x533A;&#x540E;&#x7684;&#x5185;&#x5BB9;&#xFF08;core.img&#xFF09;&#xFF0C;&#x8FD9;&#x4E9B;&#x5185;&#x5BB9;&#x7531;&#x4EE5;&#x4E0B;&#x56DB;&#x4E2A;&#x90E8;&#x5206;&#x7EC4;&#x6210;&#xFF1A;diskboot.img&#x3001;lzma_decompress.img&#x3001;kernel.img&#x4EE5;&#x53CA;&#x4E00;&#x4E9B;&#x6A21;&#x7EC4;&#x3002;&#x5982;&#x4E0B;&#x56FE;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/074238.jpg" alt="GRUB"></p><p>diskboot.img&#x4F1A;&#x89E3;&#x538B;lzma_decompress.img&#x7A0B;&#x5E8F;&#xFF0C;&#x7136;&#x540E;&#x5C06;&#x63A7;&#x5236;&#x6743;&#x8F6C;&#x4EA4;&#x7ED9;&#x5B83;&#x3002;lzma&#x5728;&#x89E3;&#x538B;&#x7F29;kernel.img&#x4E4B;&#x524D;&#xFF0C;&#x4F1A;&#x5C06;&#x8BA1;&#x7B97;&#x673A;&#x4ECE;&#x5B9E;&#x6A21;&#x5F0F;&#x8F6C;&#x5316;&#x4E3A;&#x4FDD;&#x62A4;&#x6A21;&#x5F0F;&#xFF08;&#x5B9E;&#x6A21;&#x5F0F;&#x4E0B;&#x5185;&#x5B58;&#x6700;&#x5927;&#x5BFB;&#x5740;&#x4E3A;2^20&#xFF0C;&#x800C;&#x4FDD;&#x62A4;&#x6A21;&#x5F0F;&#x4E0B;&#x5185;&#x5B58;&#x6700;&#x5927;&#x5BFB;&#x5740;&#x4E3A;2^32&#xFF09;&#xFF0C;&#x8FD9;&#x6837;&#xFF0C;&#x53EF;&#x4EE5;&#x5728;&#x89E3;&#x538B;kernel.img&#x540E;&#xFF0C;&#x5C06;&#x5176;&#x8F7D;&#x5165;&#x81F3;&#x5185;&#x5B58;&#x7A7A;&#x95F4;&#x5185;&#x6267;&#x884C;&#x3002;</p><p>&#x800C;&#x5728;&#x5207;&#x6362;&#x4E3A;&#x4FDD;&#x62A4;&#x6A21;&#x5F0F;&#x540E;&#xFF0C;&#x8BA1;&#x7B97;&#x673A;&#x4F1A;&#x5904;&#x7406;&#x5982;&#x4E0B;&#x5DE5;&#x4F5C;&#xFF1A;</p><ol><li>&#x542F;&#x7528;&#x5206;&#x6BB5;&#xFF1A;&#x6BB5;&#x5BC4;&#x5B58;&#x5668;&#x6307;&#x5411;&#x6BB5;&#x63CF;&#x8FF0;&#x7B26;&#x8868;&#xFF0C;&#x7528;&#x4E8E;&#x9694;&#x79BB;&#x4E0D;&#x540C;&#x8FDB;&#x7A0B;</li><li>&#x542F;&#x52A8;&#x5206;&#x9875;&#xFF1A;&#x5C06;&#x5185;&#x5B58;&#x5206;&#x9875;&#xFF0C;&#x65B9;&#x4FBF;&#x7A0B;&#x5E8F;&#x4F7F;&#x7528;&#x4EE5;&#x53CA;&#x7533;&#x8BF7;</li><li>&#x6253;&#x5F00;Gate A20&#x5F00;&#x5173;&#xFF1A;&#x5728;&#x5B9E;&#x6A21;&#x5F0F;&#x4E0B;&#x53EA;&#x6709;20&#x6839;&#x5730;&#x5740;&#x7EBF;&#xFF0C;&#x53EF;&#x4EE5;&#x8BBF;&#x95EE;1M&#x5185;&#x5B58;&#x7A7A;&#x95F4;&#xFF1B;&#x6240;&#x4EE5;&#xFF0C;&#x5728;&#x4FDD;&#x62A4;&#x6A21;&#x5F0F;&#x4E0B;&#xFF0C;&#x9700;&#x8981;&#x6253;&#x5F00;&#x8FD9;&#x4E2A;&#x5F00;&#x5173;&#xFF0C;&#x7528;&#x4E8E;&#x8BBF;&#x95EE;&#x8D85;&#x8FC7;1M&#x7A7A;&#x95F4;&#x7684;&#x5185;&#x5B58;</li></ol><p>&#x4E4B;&#x540E;&#xFF0C;&#x5C06;&#x4F1A;&#x89E3;&#x6790;grub&#x7684;&#x914D;&#x7F6E;&#x6587;&#x4EF6;&#xFF08;/boot/grub/grub.conf&#xFF09;&#xFF0C;&#x5E76;&#x5C06;&#x5176;&#x914D;&#x7F6E;&#x663E;&#x793A;&#xFF0C;&#x7528;&#x6237;&#x53EF;&#x4EE5;&#x9009;&#x62E9;&#x5176;&#x4E2D;&#x4E00;&#x4E2A;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#x8F7D;&#x5165;&#x3002;</p><p>&#x5728;&#x7528;&#x6237;&#x9009;&#x62E9;&#x67D0;&#x4E2A;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#x540E;&#xFF0C;GRUB&#x4F1A;&#x68C0;&#x67E5;linux&#x5185;&#x6838;&#x5934;&#x6587;&#x4EF6;&#x4FE1;&#x606F;&#x662F;&#x5426;&#x5B8C;&#x6574;&#x548C;&#x6B63;&#x5E38;&#xFF0C;&#x5E76;&#x52A0;&#x8F7D;linux&#x5185;&#x6838;&#x955C;&#x50CF;&#x5230;&#x5185;&#x5B58;&#xFF1B;&#x6700;&#x7EC8;&#x6267;&#x884C;grub_command_execute(&#x201C;boot&#x201D;, 0,0)&#x65B9;&#x6CD5;&#x542F;&#x52A8;&#x5185;&#x6838;&#xFF0C;&#x5C06;&#x63A7;&#x5236;&#x6743;&#x4EA4;&#x7531;&#x7ED9;&#x5185;&#x6838;&#x3002;</p><h3 id="&#x5185;&#x6838;&#x542F;&#x52A8;"><a href="#&#x5185;&#x6838;&#x542F;&#x52A8;" class="headerlink" title="&#x5185;&#x6838;&#x542F;&#x52A8;"></a>&#x5185;&#x6838;&#x542F;&#x52A8;</h3><p>&#x52A0;&#x8F7D;&#x5185;&#x6838;&#x955C;&#x50CF;&#x81F3;&#x5185;&#x5B58;&#x540E;&#xFF0C;linux&#x5982;&#x4F55;&#x505A;&#x7CFB;&#x7EDF;&#x521D;&#x59CB;&#x5316;&#x4EE5;&#x53CA;&#x542F;&#x52A8;&#x7B2C;&#x4E00;&#x4E2A;&#x7528;&#x6237;&#x8FDB;&#x7A0B;&#xFF1F;</p><p>&#x5185;&#x6838;&#x4F1A;&#x5904;&#x7406;&#x5982;&#x4E0B;&#x4E8B;&#x9879;&#xFF1A;</p><ol><li>&#x521D;&#x59CB;&#x5316;&#x8FDB;&#x7A0B;&#x6808;&#x4EE5;&#x53CA;&#x521D;&#x59CB;&#x5316;0&#x53F7;&#x8FDB;&#x7A0B;&#xFF08;&#x8BE5;&#x8FDB;&#x7A0B;&#x662F;&#x552F;&#x4E00;&#x6CA1;&#x6709;fork&#x6216;&#x8005;&#x901A;&#x8FC7;kernel_thread&#x4EA7;&#x751F;&#x7684;&#x8FDB;&#x7A0B;&#xFF09;</li><li>&#x4E2D;&#x65AD;&#x95E8;&#x521D;&#x59CB;&#x5316;</li><li>&#x5185;&#x5B58;&#x7BA1;&#x7406;&#x521D;&#x59CB;&#x5316;</li><li>&#x8C03;&#x5EA6;&#x7CFB;&#x7EDF;&#x521D;&#x59CB;&#x5316;</li><li>&#x865A;&#x62DF;&#x6587;&#x4EF6;&#x7CFB;&#x7EDF;&#x521D;&#x59CB;&#x5316;</li><li>1&#x53F7;&#x8FDB;&#x7A0B;&#x521D;&#x59CB;&#x5316;</li><li>2&#x53F7;&#x8FDB;&#x7A0B;&#x521D;&#x59CB;&#x5316;</li></ol><p>&#x7740;&#x91CD;&#x5BF9;&#x4E8E;1&#x53F7;&#x8FDB;&#x7A0B;&#x4EE5;&#x53CA;2&#x53F7;&#x8FDB;&#x7A0B;&#x7684;&#x521D;&#x59CB;&#x5316;&#x505A;&#x5177;&#x4F53;&#x5206;&#x6790;</p><h4 id="1&#x53F7;&#x8FDB;&#x7A0B;&#x521D;&#x59CB;&#x5316;"><a href="#1&#x53F7;&#x8FDB;&#x7A0B;&#x521D;&#x59CB;&#x5316;" class="headerlink" title="1&#x53F7;&#x8FDB;&#x7A0B;&#x521D;&#x59CB;&#x5316;"></a>1&#x53F7;&#x8FDB;&#x7A0B;&#x521D;&#x59CB;&#x5316;</h4><p>&#x5728;&#x521D;&#x59CB;&#x5B8C;&#x6210;&#x7EBF;&#x7A0B;&#x6808;&#x3001;&#x4E2D;&#x65AD;&#x95E8;&#x3001;MMU&#x3001;VFS&#x540E;&#x4F1A;&#x5F00;&#x59CB;&#x6267;&#x884C;&#x521B;&#x5EFA;&#x7B2C;&#x4E8C;&#x4E2A;&#x8FDB;&#x7A0B;&#xFF0C;&#x4E5F;&#x5C31;&#x662F;1&#x53F7;&#x8FDB;&#x7A0B;&#xFF1B;&#x8FD9;&#x4E2A;&#x8FDB;&#x7A0B;&#x5C06;&#x4F1A;&#x8FD0;&#x884C;&#x7B2C;&#x4E00;&#x4E2A;&#x7528;&#x6237;&#x8FDB;&#x7A0B;&#x3002;</p><p>&#x5B83;&#x4F1A;&#x5C1D;&#x8BD5;&#x901A;&#x8FC7;&#x4E00;&#x4E2A;&#x521D;&#x59CB;&#x5316;&#x6587;&#x4EF6;&#x6765;&#x6267;&#x884C;&#xFF0C;&#x4E0D;&#x540C;linux&#x7248;&#x672C;&#x53EF;&#x80FD;&#x8FD0;&#x884C;&#x7684;&#x6587;&#x4EF6;&#x4E0D;&#x540C;&#xFF1A;</p><ol><li>/sbin/init</li><li>/etc/init</li><li>/bin/init</li><li>/bin/sh</li></ol><p>&#x6267;&#x884C;init&#x6587;&#x4EF6;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x5B83;&#x4F1A;&#x5904;&#x7406;&#x5982;&#x4E0B;&#x4E8B;&#x9879;&#xFF1F;</p><ol><li>&#x8F7D;&#x5165;ELF&#xFF08;&#x7528;&#x4E8E;&#x89C4;&#x5B9A;&#x7A0B;&#x5E8F;&#x8F7D;&#x5165;&#x7684;&#x5185;&#x5B58;&#x683C;&#x5F0F;&#xFF09;</li><li>&#x542F;&#x52A8;&#x7528;&#x6237;&#x7EBF;&#x7A0B;</li></ol><p>&#x81EA;&#x6B64;&#xFF0C;1&#x53F7;&#x8FDB;&#x7A0B;&#x4F5C;&#x4E3A;&#x6240;&#x6709;&#x7528;&#x6237;&#x6001;&#x8FDB;&#x7A0B;&#x5B58;&#x5728;</p><h4 id="2&#x53F7;&#x8FDB;&#x7A0B;&#x521D;&#x59CB;&#x5316;"><a href="#2&#x53F7;&#x8FDB;&#x7A0B;&#x521D;&#x59CB;&#x5316;" class="headerlink" title="2&#x53F7;&#x8FDB;&#x7A0B;&#x521D;&#x59CB;&#x5316;"></a>2&#x53F7;&#x8FDB;&#x7A0B;&#x521D;&#x59CB;&#x5316;</h4><p>&#x5728;1&#x53F7;&#x8FDB;&#x7A0B;&#x5B8C;&#x6210;&#x7528;&#x6237;&#x7EBF;&#x7A0B;&#x542F;&#x52A8;&#x540E;&#xFF0C;rest_init&#x51FD;&#x6570;&#x8FD8;&#x521B;&#x5EFA;&#x4E86;2&#x53F7;&#x8FDB;&#x7A0B;&#x7528;&#x4E8E;&#x7BA1;&#x7406;&#x6240;&#x6709;&#x7684;&#x5185;&#x6838;&#x6001;&#x8FDB;&#x7A0B;&#x3002;</p><h3 id="&#x603B;&#x7ED3;"><a href="#&#x603B;&#x7ED3;" class="headerlink" title="&#x603B;&#x7ED3;"></a>&#x603B;&#x7ED3;</h3><p>linux&#x542F;&#x52A8;&#x8FC7;&#x7A0B;&#x5728;&#x6B64;&#x544A;&#x4E00;&#x6BB5;&#x843D;&#xFF0C;&#x4E4B;&#x540E;&#x53EF;&#x80FD;&#x4F1A;&#x5BF9;&#x8FD9;&#x4E2A;&#x8FC7;&#x7A0B;&#x505A;&#x66F4;&#x8BE6;&#x7EC6;&#x7684;&#x5206;&#x6790;&#x4EE5;&#x53CA;&#x8BF4;&#x660E;&#x3002;</p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;一直想要自己做出一个操作系统，因此对于现有linux需要有个详细的了解，知道操作系统如何实现所有的过程。因此，在这篇文章中记录下linux的详细启动过程。&lt;/p&gt;&lt;p&gt;本篇打算从三个部分讲解Linux启动的过程：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;BIOS阶段&lt;/li&gt;&lt;li&gt;BootLoader阶段&lt;/li&gt;&lt;li&gt;内核启动阶段&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;本文前提：非UEFI模式&lt;/p&gt;
    
    </summary>
    
      <category term="Linux" scheme="https://xuqiang.me/categories/Linux/"/>
    
    
      <category term="linux" scheme="https://xuqiang.me/tags/linux/"/>
    
      <category term="bios" scheme="https://xuqiang.me/tags/bios/"/>
    
      <category term="kernel" scheme="https://xuqiang.me/tags/kernel/"/>
    
      <category term="mbr" scheme="https://xuqiang.me/tags/mbr/"/>
    
  </entry>
  
  <entry>
    <title>ES查询中如何获取并解析查询字段</title>
    <link href="https://xuqiang.me/how-es-choose-and-get-filed-info.html"/>
    <id>https://xuqiang.me/how-es-choose-and-get-filed-info.html</id>
    <published>2019-10-02T16:22:19.000Z</published>
    <updated>2019-10-03T15:05:25.747Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x6700;&#x8FD1;&#x5728;&#x5B66;&#x4E60;Elasticsearch&#x76F8;&#x5173;&#x7684;&#x4E00;&#x4E9B;&#x539F;&#x7406;&#xFF0C;&#x7136;&#x540E;&#x5728;&#x6620;&#x50CF;&#x4E2D;ES&#x7684;text&#x5B57;&#x6BB5;&#x5982;&#x679C;&#x5B58;&#x5728;keyword&#x7684;fields&#xFF0C;&#x5219;&#x4F1A;&#x5728;&#x805A;&#x5408;&#x7684;&#x65F6;&#x5019;&#x9009;&#x62E9;keyword&#x7C7B;&#x578B;&#x8FDB;&#x884C;&#x805A;&#x5408;&#xFF0C;&#x540C;&#x65F6;&#x5728;&#x6587;&#x672C;&#x68C0;&#x7D22;&#x7684;&#x65F6;&#x5019;&#x6839;&#x636E;text&#x7C7B;&#x578B;&#x5206;&#x8BCD;&#x68C0;&#x7D22;&#x3002;&#x56E0;&#x6B64;&#xFF0C;&#x60F3;&#x63A2;&#x7A76;&#x4E0B;&#x8FD9;&#x4E2A;&#x7684;&#x5B9E;&#x73B0;&#x8FC7;&#x7A0B;&#x3002;</p><a id="more"></a><h3 id="ES&#x67E5;&#x8BE2;&#x539F;&#x7406;"><a href="#ES&#x67E5;&#x8BE2;&#x539F;&#x7406;" class="headerlink" title="ES&#x67E5;&#x8BE2;&#x539F;&#x7406;"></a>ES&#x67E5;&#x8BE2;&#x539F;&#x7406;</h3><p>&#x9700;&#x8981;&#x4E86;&#x89E3;keyword&#x7684;&#x9009;&#x62E9;&#x90ED;&#x6210;&#xFF0C;&#x9700;&#x8981;&#x6307;&#x5B9A;&#x5982;&#x4E0B;&#x4E24;&#x70B9;&#xFF1A;</p><ol><li>&#x5B57;&#x6BB5;&#x5728;&#x542F;&#x52A8;&#x8FC7;&#x7A0B;&#x4E2D;&#x5982;&#x4F55;&#x521D;&#x59CB;&#x5316;</li><li>&#x67E5;&#x8BE2;&#x7684;&#x65F6;&#x5019;&#x5982;&#x4F55;&#x7B5B;&#x9009;&#x9700;&#x8981;&#x7684;&#x5B57;&#x6BB5;&#x4EE5;&#x53CA;&#x9009;&#x62E9;&#x7C7B;&#x578B;</li></ol><h4 id="ES&#x521D;&#x59CB;&#x5316;&#x6D41;&#x7A0B;"><a href="#ES&#x521D;&#x59CB;&#x5316;&#x6D41;&#x7A0B;" class="headerlink" title="ES&#x521D;&#x59CB;&#x5316;&#x6D41;&#x7A0B;"></a>ES&#x521D;&#x59CB;&#x5316;&#x6D41;&#x7A0B;</h4><p>&#x901A;&#x8FC7;&#x4EE5;&#x4E0B;&#x65F6;&#x5E8F;&#x56FE;&#x8BB0;&#x5F55;&#x4E0B;ES&#x521D;&#x59CB;&#x5316;&#x8FC7;&#x7A0B;&#x4E2D;&#x7684;&#x5927;&#x81F4;&#x8FC7;&#x7A0B;&#xFF1A;</p><pre class="mermaid">sequenceDiagram;  Elasticsearch-&gt;&gt;Command: &#x4E3B;&#x7A0B;&#x5E8F;&#x5165;&#x53E3;&#xFF0C;&#x89E3;&#x6790;&#x547D;&#x4EE4;&#x53C2;&#x6570;  Command-&gt;&gt;Command: &#x6CE8;&#x518C;closeHook&#xFF0C;&#x6267;&#x884C;&#x4E3B;&#x51FD;&#x6570;&#x524D;&#x7F6E;hook&#x51FD;&#x6570;beforeMain.run()  Command-&gt;&gt;EnvironmentAwareCommand: &#x6267;&#x884C;&#x73AF;&#x5883;&#x53C2;&#x6570;&#x521D;&#x59CB;&#x5316;  EnvironmentAwareCommand-&gt;&gt;Elasticsearch: &#x6267;&#x884C;&#x542F;&#x52A8;&#x5177;&#x4F53;&#x547D;&#x4EE4;  Elasticsearch-&gt;&gt;Elasticsearch: &#x53C2;&#x6570;&#x89E3;&#x6790;  Elasticsearch-&gt;&gt;Bootstrap: &#x6267;&#x884C;&#x521D;&#x59CB;&#x5316;&#x9759;&#x6001;&#x65B9;&#x6CD5;init  Bootstrap-&gt;&gt;Bootstrap: &#x5B9E;&#x4F8B;&#x5316;Bootstrap&#xFF0C;&#x521D;&#x59CB;&#x5316;keepAlive&#x7EBF;&#x7A0B;  Bootstrap-&gt;&gt;Bootstrap: &#x521B;&#x5EFA;&#x4E0A;&#x4E0B;&#x6587;&#x73AF;&#x5883;&#xFF0C;&#x8BBE;&#x7F6E;&#x73AF;&#x5883;&#x7684;&#x65E5;&#x5FD7;&#x914D;&#x7F6E;  Bootstrap-&gt;&gt;Bootstrap: &#x521B;&#x5EFA;PID&#x6587;&#x4EF6;  Bootstrap-&gt;&gt;Bootstrap: &#x68C0;&#x67E5;luence&#x7248;&#x672C;  Bootstrap-&gt;&gt;Bootstrap: &#x521D;&#x59CB;&#x5316;&#x63D2;&#x4EF6;&#x8FDB;&#x7A0B;&#xFF0C;&#x521D;&#x59CB;&#x5316;&#x8282;&#x70B9;  Bootstrap-&gt;&gt;Bootstrap: &#x8282;&#x70B9;&#x542F;&#x52A8;&#x4EE5;&#x53CA;&#x4FDD;&#x6D3B;&#x7EBF;&#x7A0B;&#x542F;&#x52A8;  BootStrap-&gt;&gt;Node: &#x5C1D;&#x8BD5;&#x542F;&#x52A8;&#x8282;&#x70B9;  Node-&gt;&gt;Node: &#x8282;&#x70B9;&#x72B6;&#x6001;&#x66F4;&#x6539;  Node-&gt;&gt;Node: &#x5404;&#x670D;&#x52A1;&#x521D;&#x59CB;&#x5316;&#x542F;&#x52A8;  Node-&gt;&gt;Node: Netty&#x670D;&#x52A1;&#x542F;&#x52A8;  alt: &#x5F53;&#x524D;&#x8282;&#x70B9;&#x4E3A;Master/Data    Node-&gt;&gt;Node: &#x83B7;&#x53D6;GatewayMetaState&#x5B9E;&#x4F8B;    Node-&gt;&gt;GatewayMetaState: &#x6267;&#x884C;loadMetaState&#x8F7D;&#x5165;&#x5143;&#x4FE1;&#x606F;    GatewayMetaState-&gt;&gt;MetaStateService: &#x6267;&#x884C;loadFullState&#x65B9;&#x6CD5;&#x8F7D;&#x5165;&#x5168;&#x5C40;&#x72B6;&#x6001;&#x4EE5;&#x53CA;&#x7D22;&#x5F15;&#x72B6;&#x6001;    MetaStateService-&gt;&gt;MetaStateService: &#x8F7D;&#x5165;&#x5168;&#x5C40;&#x72B6;&#x6001;    MetaStateService-&gt;&gt;MetaStateService: &#x67E5;&#x627E;&#x6240;&#x6709;&#x7684;&#x7D22;&#x5F15;&#x8DEF;&#x5F84;    MetaStateService-&gt;&gt;MetaStateService: &#x89E3;&#x6790;&#x6BCF;&#x4E2A;&#x7D22;&#x5F15;&#x8DEF;&#x5F84;&#xFF0C;&#x8F7D;&#x5165;&#x6700;&#x65B0;&#x7684;&#x72B6;&#x6001;    MetaStateService-&gt;&gt;MetaStateService: &#x5C06;&#x7D22;&#x5F15;&#x72B6;&#x6001;&#x653E;&#x5165;&#x5168;&#x5C40;&#x72B6;&#x6001;&#x5185;&#x7F13;&#x5B58;  else:    Node-&gt;&gt;Node: &#x521B;&#x5EFA;&#x7A7A;&#x7684;&#x5143;&#x4FE1;&#x606F;  end  Node-&gt;&gt;Node: &#x542F;&#x52A8;Discovery&#x670D;&#x52A1;&#x4EE5;&#x53CA;Cluster&#x670D;&#x52A1;  Node-&gt;&gt;Node: &#x8282;&#x70B9;Transport&#x670D;&#x52A1;&#x5F00;&#x59CB;&#x63A5;&#x6536;&#x8BF7;&#x6C42;  Node-&gt;&gt;Node: &#x521D;&#x59CB;&#x5316;&#x96C6;&#x7FA4;&#x72B6;&#x6001;&#xFF0C;&#x5E76;&#x76D1;&#x542C;&#x96C6;&#x7FA4;&#x72B6;&#x6001;&#x53D8;&#x66F4;  alt: &#x542F;&#x7528;HTTP&#x6A21;&#x5757;    Node-&gt;&gt;Node: &#x521D;&#x59CB;&#x5316;HTTP&#x670D;&#x52A1;&#xFF0C;&#x5E76;&#x542F;&#x52A8;  end  alt: &#x662F;&#x5426;&#x5C06;&#x7AEF;&#x53E3;&#x4FE1;&#x606F;&#x5199;&#x5165;&#x6587;&#x4EF6;    alt: &#x542F;&#x7528;HTTP&#x6A21;&#x5757;      Node-&gt;&gt;Node: &#x5C06;http&#x7AEF;&#x53E3;&#x5199;&#x5165;    end    Node-&gt;&gt;Node: &#x5C06;transport&#x7AEF;&#x53E3;&#x5199;&#x5165;  end  Node-&gt;&gt;Node: &#x96C6;&#x7FA4;&#x63D2;&#x4EF6;&#x6267;&#x884C;onNodeStarted&#x65B9;&#x6CD5;&#x8FDB;&#x884C;&#x8282;&#x70B9;&#x521D;&#x59CB;&#x5316;</pre><p>&#x4E0A;&#x8FF0;&#x6D41;&#x7A0B;&#x5927;&#x81F4;&#x5C06;ES&#x6574;&#x4E2A;&#x542F;&#x52A8;&#x6D41;&#x7A0B;&#x5927;&#x6982;&#x8BB2;&#x8FF0;&#x4E86;&#x4E00;&#x904D;&#xFF0C;&#x5177;&#x4F53;&#x4E86;&#x89E3;&#x4E0B;&#x5728;&#x52A0;&#x8F7D;&#x8FC7;&#x7A0B;&#x4E2D;&#x5982;&#x4F55;&#x89E3;&#x6790;&#x6570;&#x636E;&#x6587;&#x4EF6;&#x5E76;&#x5C06;&#x5176;&#x52A0;&#x5165;&#x7F13;&#x5B58;&#x3002;</p><p>&#x5728;&#x4E0A;&#x8FF0;&#x6D41;&#x7A0B;&#x4E2D;&#x53EF;&#x4EE5;&#x627E;&#x5230;&#x5982;&#x4E0B;&#x8FD9;&#x4E00;&#x5757;&#x662F;&#x91CD;&#x70B9;&#xFF1A;</p><pre class="mermaid">sequenceDiagram;  Node-&gt;&gt;Node: &#x83B7;&#x53D6;GatewayMetaState&#x5B9E;&#x4F8B;  Node-&gt;&gt;GatewayMetaState: &#x6267;&#x884C;loadMetaState&#x8F7D;&#x5165;&#x5143;&#x4FE1;&#x606F;  GatewayMetaState-&gt;&gt;MetaStateService: &#x6267;&#x884C;loadFullState&#x65B9;&#x6CD5;&#x8F7D;&#x5165;&#x5168;&#x5C40;&#x72B6;&#x6001;&#x4EE5;&#x53CA;&#x7D22;&#x5F15;&#x72B6;&#x6001;  MetaStateService-&gt;&gt;MetaStateService: &#x8F7D;&#x5165;&#x5168;&#x5C40;&#x72B6;&#x6001;  MetaStateService-&gt;&gt;MetaStateService: &#x67E5;&#x627E;&#x6240;&#x6709;&#x7684;&#x7D22;&#x5F15;&#x8DEF;&#x5F84;  MetaStateService-&gt;&gt;MetaStateService: &#x89E3;&#x6790;&#x6BCF;&#x4E2A;&#x7D22;&#x5F15;&#x8DEF;&#x5F84;&#xFF0C;&#x8F7D;&#x5165;&#x6700;&#x65B0;&#x7684;&#x72B6;&#x6001;  MetaStateService-&gt;&gt;MetaStateService: &#x5C06;&#x7D22;&#x5F15;&#x72B6;&#x6001;&#x653E;&#x5165;&#x5168;&#x5C40;&#x72B6;&#x6001;&#x5185;&#x7F13;&#x5B58;</pre><p>&#x8F7D;&#x5165;&#x6BCF;&#x4E2A;&#x7D22;&#x5F15;&#x6700;&#x65B0;&#x7684;&#x72B6;&#x6001;&#x4EE3;&#x7801;&#x5982;&#x4E0B;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span>  T <span class="title">loadLatestState</span><span class="params">(Logger logger, NamedXContentRegistry namedXContentRegistry, Path... dataLocations)</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line">  List&lt;PathAndStateId&gt; files = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">  <span class="keyword">long</span> maxStateId = -<span class="number">1</span>;</span><br><span class="line">  <span class="keyword">boolean</span> maxStateIdIsLegacy = <span class="keyword">true</span>;</span><br><span class="line">  <span class="keyword">if</span> (dataLocations != <span class="keyword">null</span>) {</span><br><span class="line">      <span class="comment">// &#x5BF9;&#x4E8E;&#x6570;&#x636E;&#x6587;&#x4EF6;&#x4F4D;&#x7F6E;&#x5217;&#x8868;&#x505A;&#x904D;&#x5386;</span></span><br><span class="line">      <span class="keyword">for</span> (Path dataLocation : dataLocations) {</span><br><span class="line">          <span class="keyword">final</span> Path stateDir = dataLocation.resolve(STATE_DIR_NAME);</span><br><span class="line">          <span class="keyword">try</span> (DirectoryStream&lt;Path&gt; paths = Files.newDirectoryStream(stateDir)) {</span><br><span class="line">              <span class="keyword">for</span> (Path stateFile : paths) {</span><br><span class="line">                  <span class="comment">// &#x7B5B;&#x9009;&#x72B6;&#x6001;&#x6587;&#x4EF6;</span></span><br><span class="line">                  <span class="keyword">final</span> Matcher matcher = stateFilePattern.matcher(stateFile.getFileName().toString());</span><br><span class="line">                  <span class="keyword">if</span> (matcher.matches()) {</span><br><span class="line">                      <span class="keyword">final</span> <span class="keyword">long</span> stateId = Long.parseLong(matcher.group(<span class="number">1</span>));</span><br><span class="line">                      maxStateId = Math.max(maxStateId, stateId);</span><br><span class="line">                      <span class="keyword">final</span> <span class="keyword">boolean</span> legacy = MetaDataStateFormat.STATE_FILE_EXTENSION.equals(matcher.group(<span class="number">2</span>)) == <span class="keyword">false</span>;</span><br><span class="line">                      maxStateIdIsLegacy &amp;= legacy;</span><br><span class="line">                      PathAndStateId pav = <span class="keyword">new</span> PathAndStateId(stateFile, stateId, legacy);</span><br><span class="line">                      logger.trace(<span class="string">&quot;found state file: {}&quot;</span>, pav);</span><br><span class="line">                      <span class="comment">// &#x52A0;&#x5165;&#x6587;&#x4EF6;&#x5217;&#x8868;</span></span><br><span class="line">                      files.add(pav);</span><br><span class="line">                  }</span><br><span class="line">              }</span><br><span class="line">          } <span class="keyword">catch</span> (NoSuchFileException | FileNotFoundException ex) {</span><br><span class="line">              <span class="comment">// no _state directory -- move on</span></span><br><span class="line">          }</span><br><span class="line">      }</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">final</span> List&lt;Throwable&gt; exceptions = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">  T state = <span class="keyword">null</span>;</span><br><span class="line">  <span class="comment">// &#x7B5B;&#x9009;&#x51FA;&#x6700;&#x5927;&#x7248;&#x672C;&#x53F7;&#x7684;&#x6700;&#x65B0;&#x7D22;&#x5F15;&#x6587;&#x4EF6;</span></span><br><span class="line">  Collection&lt;PathAndStateId&gt; pathAndStateIds = files</span><br><span class="line">          .stream()</span><br><span class="line">          .filter(<span class="keyword">new</span> StateIdAndLegacyPredicate(maxStateId, maxStateIdIsLegacy))</span><br><span class="line">          .collect(Collectors.toCollection(ArrayList::<span class="keyword">new</span>));</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> (PathAndStateId pathAndStateId : pathAndStateIds) {</span><br><span class="line">      <span class="keyword">try</span> {</span><br><span class="line">          <span class="keyword">final</span> Path stateFile = pathAndStateId.file;</span><br><span class="line">          <span class="keyword">final</span> <span class="keyword">long</span> id = pathAndStateId.id;</span><br><span class="line">          <span class="keyword">if</span> (pathAndStateId.legacy) {</span><br><span class="line">              <span class="comment">// &#x65E7;&#x7248;&#x683C;&#x5F0F;</span></span><br><span class="line">              <span class="keyword">final</span> <span class="keyword">byte</span>[] data = Files.readAllBytes(stateFile);</span><br><span class="line">              <span class="keyword">if</span> (data.length == <span class="number">0</span>) {</span><br><span class="line">                  logger.debug(<span class="string">&quot;{}: no data for [{}], ignoring...&quot;</span>, prefix, stateFile.toAbsolutePath());</span><br><span class="line">                  <span class="keyword">continue</span>;</span><br><span class="line">              }</span><br><span class="line">              <span class="comment">// &#x89E3;&#x6790;&#x6587;&#x4EF6;&#x5185;&#x5BB9;</span></span><br><span class="line">              <span class="keyword">try</span> (XContentParser parser = XContentHelper.createParser(namedXContentRegistry, <span class="keyword">new</span> BytesArray(data))) {</span><br><span class="line">                  state = fromXContent(parser);</span><br><span class="line">              }</span><br><span class="line">              <span class="keyword">if</span> (state == <span class="keyword">null</span>) {</span><br><span class="line">                  logger.debug(<span class="string">&quot;{}: no data for [{}], ignoring...&quot;</span>, prefix, stateFile.toAbsolutePath());</span><br><span class="line">              }</span><br><span class="line">          } <span class="keyword">else</span> {</span><br><span class="line">              <span class="comment">// &#x6700;&#x65B0;&#x7248;&#x672C;&#x683C;&#x5F0F;&#x8BFB;&#x53D6;</span></span><br><span class="line">              state = read(namedXContentRegistry, stateFile);</span><br><span class="line">              logger.trace(<span class="string">&quot;state id [{}] read from [{}]&quot;</span>, id, stateFile.getFileName());</span><br><span class="line">          }</span><br><span class="line">          <span class="keyword">return</span> state;</span><br><span class="line">      } <span class="keyword">catch</span> (Exception e) {</span><br><span class="line">          exceptions.add(<span class="keyword">new</span> IOException(<span class="string">&quot;failed to read &quot;</span> + pathAndStateId.toString(), e));</span><br><span class="line">          logger.debug(</span><br><span class="line">              (Supplier&lt;?&gt;) () -&gt; <span class="keyword">new</span> ParameterizedMessage(</span><br><span class="line">                  <span class="string">&quot;{}: failed to read [{}], ignoring...&quot;</span>, pathAndStateId.file.toAbsolutePath(), prefix), e);</span><br><span class="line">      }</span><br><span class="line">  }</span><br><span class="line">  <span class="comment">// ....</span></span><br><span class="line">  <span class="keyword">return</span> state;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728;&#x65B9;&#x6CD5;<code>read</code>&#x5185;&#x4F1A;&#x89E3;&#x6790;&#x771F;&#x6B63;&#x7684;&#x6587;&#x4EF6;&#x5185;&#x5BB9;&#x3002;</p><h4 id="ES&#x805A;&#x5408;&#x67E5;&#x8BE2;&#x6D41;&#x7A0B;"><a href="#ES&#x805A;&#x5408;&#x67E5;&#x8BE2;&#x6D41;&#x7A0B;" class="headerlink" title="ES&#x805A;&#x5408;&#x67E5;&#x8BE2;&#x6D41;&#x7A0B;"></a>ES&#x805A;&#x5408;&#x67E5;&#x8BE2;&#x6D41;&#x7A0B;</h4><p>ES&#x6BCF;&#x4E00;&#x6B21;&#x67E5;&#x8BE2;&#x901A;&#x8FC7;<code>netty</code>&#x670D;&#x52A1;&#x4F20;&#x9012;&#x67E5;&#x8BE2;&#x547D;&#x4EE4;&#xFF0C;&#x4EE5;&#x4E0B;&#x662F;&#x805A;&#x5408;&#x67E5;&#x8BE2;&#x6D41;&#x7A0B;&#xFF1A;</p><pre class="mermaid">sequenceDiagram;  Netty4HttpRequestHandler-&gt;&gt;Netty4HttpRequestHandler: &#x8BFB;&#x53D6;&#x6570;&#x636E;  Netty4HttpRequestHandler-&gt;&gt;Netty4HttpServerTransport: &#x4F20;&#x8F93;&#x8BF7;&#x6C42;  Netty4HttpServerTransport-&gt;&gt;RestController: &#x5206;&#x53D1;&#x8BF7;&#x6C42;  RestController-&gt;&gt;RestController: &#x904D;&#x5386;&#x6240;&#x6709;&#x5904;&#x7406;&#x5668;&#xFF0C;&#x67E5;&#x627E;&#x5339;&#x914D;&#x7684;handler  alt &#x67E5;&#x627E;&#x5230;&#x5339;&#x914D;&#x7684;:    RestController-&gt;&gt;BaseRestHandler: &#x5904;&#x7406;&#x8BF7;&#x6C42;    BaseRestHandler-&gt;&gt;RestSearchAction: &#x89E3;&#x6790;&#x8BF7;&#x6C42;&#x83B7;&#x53D6;&#x5177;&#x4F53;&#x7684;&#x5904;&#x7F6E;&#x52A8;&#x4F5C;    RestSearchAction-&gt;&gt;SearchSourceBuilder: &#x6839;&#x636E;&#x4F20;&#x9012;&#x8FC7;&#x6765;&#x7684;json&#x5B57;&#x7B26;&#x4E32;&#x89E3;&#x6790;&#x8BF7;&#x6C42;&#x5185;&#x5BB9;    SearchSourceBuilder-&gt;&gt;SearchSourceBuilder: &#x6839;&#x636E;string token&#xFF0C;&#x5224;&#x65AD;&#x4E0D;&#x540C;&#x7C7B;&#x578B;&#xFF0C;&#x89E3;&#x6790;&#x4E0D;&#x540C;&#x7684;&#x6570;&#x636E;    SearchSourceBuilder-&gt;&gt;AggregatorFactories: &#x4ECE;&#x5B57;&#x7B26;&#x4E32;&#x4E2D;&#x6784;&#x5EFA;&#x51FA;&#x805A;&#x5408;&#x5DE5;&#x5382;&#x7528;&#x4E8E;&#x540E;&#x7EED;&#x6784;&#x5EFA;&#x805A;&#x5408;    AggregatorFactories-&gt;&gt;AggregatorFactories: &#x6784;&#x5EFA;&#x805A;&#x5408;&#x5DE5;&#x5382;    AggregatorFactories-&gt;&gt;SearchSourceBuilder: &#x7EE7;&#x7EED;&#x89E3;&#x6790;&#x5176;&#x4ED6;&#x5185;&#x5BB9;    SearchSourceBuilder-&gt;&gt;RestSearchAction: &#x89E3;&#x6790;&#x5B8C;&#x6210;    RestSearchAction-&gt;&gt;RestSearchAction: &#x89E3;&#x6790;&#x67E5;&#x8BE2;&#x7C7B;&#x578B;&#x3001;&#x8DEF;&#x7531;&#x3001;&#x7D22;&#x5F15;&#x9009;&#x9879;&#x4EE5;&#x53CA;&#x6DF1;&#x5EA6;&#x5206;&#x9875;&#x8BF7;&#x6C42;&#x4FE1;&#x606F;&#x7B49;&#x7B49;    RestSearchAction-&gt;&gt;BaseRestHandler: &#x8FD4;&#x56DE;&#x9884;&#x5904;&#x7406;&#x5B8C;&#x6210;&#x7684;Action    alt: &#x5B58;&#x5728;&#x6709;&#x53C2;&#x6570;&#x672A;&#x5904;&#x7406;      BaseRestHandler-&gt;&gt;BaseRestHandler: &#x629B;&#x51FA;&#x5F02;&#x5E38;    end    BaseRestHandler-&gt;&gt;BaseRestHandler: &#x4F7F;&#x7528;&#x8BA1;&#x6570;+1    BaseRestHandler-&gt;&gt;RestSearchAction: &#x5C06;&#x8BF7;&#x6C42;&#x4EA4;&#x7531;RestSearchAction&#x5904;&#x7406;    RestSearchAction-&gt;&gt;TransportSearchAction: &#x67E5;&#x8BE2;action&#x4EA4;&#x7531;&#x5177;&#x4F53;Transport&#x6267;&#x884C;    TransportSearchAction-&gt;&gt;TransportSearchAction: &#x6839;&#x636E;state&#x4EE5;&#x53CA;&#x8BF7;&#x6C42;&#x83B7;&#x53D6;&#x5177;&#x4F53;&#x7684;&#x7D22;&#x5F15;    TransportSearchAction-&gt;&gt;TransportSearchAction: &#x9884;&#x5904;&#x7406;&#x522B;&#x540D;    TransportSearchAction-&gt;&gt;TransportSearchAction: &#x67E5;&#x8BE2;&#x8BF7;&#x6C42;&#x8DEF;&#x7531;    TransportSearchAction-&gt;&gt;TransportSearchAction: &#x83B7;&#x53D6;&#x7D22;&#x5F15;&#x5728;&#x6240;&#x6709;shards&#x4E0A;&#x7684;&#x904D;&#x5386;&#x5668;    TransportSearchAction-&gt;&gt;AbstractSearchAsyncAction: &#x5F02;&#x6B65;&#x67E5;&#x8BE2;&#x89E3;&#x6790;    AbstractSearchAsyncAction-&gt;&gt;InitialSearchPhase: &#x6267;&#x884C;&#x5F02;&#x6B65;&#x67E5;&#x8BE2;&#x8BF7;&#x6C42;    InitialSearchPhase-&gt;&gt;InitialSearchPhase: &#x5206;&#x7247;&#x904D;&#x5386;&#x5E76;&#x5728;&#x6BCF;&#x4E2A;&#x5206;&#x7247;&#x4E0A;&#x6267;&#x884C;&#x67E5;&#x8BE2;    InitialSearchPhase-&gt;&gt;SearchQueryThenFetchAsyncAction: &#x4F20;&#x9012;&#x5206;&#x7247;&#x4FE1;&#x606F;&#x4EE5;&#x53CA;&#x67E5;&#x8BE2;&#x8BF7;&#x6C42;    SearchQueryThenFetchAsyncAction-&gt;&gt;TransportService: &#x5C06;&#x67E5;&#x8BE2;&#x5F02;&#x6B65;&#x8BF7;&#x6C42;&#x4EA4;&#x7531;Transport&#x670D;&#x52A1;&#x6765;&#x6267;&#x884C;    TransportService-&gt;&gt;TransportService: &#x4EA4;&#x7531;localNodeConnection&#x6267;&#x884C;&#x67E5;&#x8BE2;&#x8BF7;&#x6C42;    TransportService-&gt;&gt;SearchTransportService: &#x5C06;&#x8BF7;&#x6C42;&#x4F20;&#x9012;    SearchTransportService-&gt;&gt;SearchService: &#x6267;&#x884C;searchService&#x8BF7;&#x6C42;&#x67E5;&#x8BE2;&#x4F20;&#x5165;&#x8BF7;&#x6C42;&#x4EE5;&#x53CA;&#x56DE;&#x8C03;&#x76D1;&#x542C;    SearchService-&gt;&gt;SearchService: &#x6267;&#x884C;&#x67E5;&#x8BE2;&#x89E3;&#x6790;&#x5E76;&#x67E5;&#x8BE2;&#x5177;&#x4F53;&#x7ED3;&#x679C;    SearchService-&gt;&gt;QueryPhase: &#x67E5;&#x8BE2;&#x89E3;&#x6790;    QueryPhase-&gt;&gt;AggregationPhase: &#x805A;&#x5408;&#x9884;&#x5904;&#x7406;&#xFF0C;&#x6784;&#x5EFA;&#x9876;&#x5C42;&#x805A;&#x5408;    AggregationPhase-&gt;&gt;QueryPhase: &#x9884;&#x5904;&#x7406;&#x5B8C;&#x6210;    QueryPhase-&gt;&gt;QueryPhase: &#x805A;&#x5408;&#x8BED;&#x53E5;&#x6267;&#x884C;    QueryPhase-&gt;&gt;QueryPhase: &#x8FD4;&#x56DE;&#x6267;&#x884C;&#x7ED3;&#x679C;    QueryPhase-&gt;&gt;SearchService: &#x7ED3;&#x679C;&#x8FD4;&#x56DE;  end</pre><p>&#x4E0A;&#x8FF0;&#x7684;&#x6574;&#x4E2A;&#x6D41;&#x7A0B;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x6709;&#x4E09;&#x5904;&#x5730;&#x65B9;&#x5BF9;&#x4E8E;&#x805A;&#x5408;&#x505A;&#x4E86;&#x5904;&#x7406;&#xFF1A;</p><ol><li>&#x8BF7;&#x6C42;&#x5B57;&#x7B26;&#x4E32;&#x89E3;&#x6790;&#x51FA;&#x805A;&#x5408;&#x6784;&#x5EFA;&#x5668;</li><li>&#x9884;&#x5904;&#x7406;&#x805A;&#x5408;&#x6784;&#x5EFA;&#x5668;&#xFF0C;&#x6784;&#x5EFA;&#x51FA;top&#x805A;&#x5408;</li><li>&#x805A;&#x5408;&#x8BED;&#x53E5;&#x6267;&#x884C;</li></ol><p>&#x8FD9;&#x4E09;&#x5904;&#x5730;&#x65B9;&#xFF0C;&#x5E76;&#x6CA1;&#x6709;&#x5BF9;&#x4E8E;&#x805A;&#x5408;&#x5B57;&#x6BB5;&#x505A;&#x7279;&#x6B8A;&#x5224;&#x65AD;&#xFF0C;&#x6BD4;&#x5982;&#x5728;&#x805A;&#x5408;&#x7684;&#x65F6;&#x5019;&#x4F1A;&#x76F4;&#x63A5;&#x9009;&#x62E9;keyword&#x5C5E;&#x6027;&#x3002;&#x800C;&#x662F;&#x9700;&#x8981;&#x5728;&#x8BF7;&#x6C42;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x663E;&#x793A;&#x6307;&#x5B9A;&#x5B57;&#x6BB5;&#x7C7B;&#x578B;&#x4E3A;keyword&#x7C7B;&#x578B;&#x7684;&#x6807;&#x8BC6;&#x3002;</p><h3 id="&#x603B;&#x7ED3;"><a href="#&#x603B;&#x7ED3;" class="headerlink" title="&#x603B;&#x7ED3;"></a>&#x603B;&#x7ED3;</h3><p>&#x5982;&#x679C;&#x9700;&#x8981;&#x5728;&#x805A;&#x5408;&#x7684;&#x65F6;&#x5019;&#x76F4;&#x63A5;&#x4F7F;&#x7528;keyword&#xFF0C;&#x5219;&#x663E;&#x793A;&#x6307;&#x5B9A;&#x5B83;&#x3002;</p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;最近在学习Elasticsearch相关的一些原理，然后在映像中ES的text字段如果存在keyword的fields，则会在聚合的时候选择keyword类型进行聚合，同时在文本检索的时候根据text类型分词检索。因此，想探究下这个的实现过程。&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="Elasticsearch" scheme="https://xuqiang.me/categories/Java/Elasticsearch/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="es" scheme="https://xuqiang.me/tags/es/"/>
    
      <category term="field" scheme="https://xuqiang.me/tags/field/"/>
    
  </entry>
  
  <entry>
    <title>ImportResource注解引发的血案</title>
    <link href="https://xuqiang.me/importResource-badcase.html"/>
    <id>https://xuqiang.me/importResource-badcase.html</id>
    <published>2019-08-30T16:28:07.000Z</published>
    <updated>2019-08-30T17:30:28.843Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p><code>SpringBoot</code>&#x9879;&#x76EE;&#x589E;&#x52A0;<code>Spring</code>&#x62E6;&#x622A;&#x5668;&#xFF0C;&#x4F46;&#x662F;&#x5374;&#x53D1;&#x73B0;&#x6CA1;&#x6709;&#x751F;&#x6548;&#xFF1B;<code>debug DispatchServelt</code>&#xFF0C;&#x53D1;&#x73B0;&#x5728;&#x67E5;&#x627E;<code>handler</code>&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x7531;&#x4E8E;&#x5B58;&#x5728;&#x591A;&#x4E2A;<code>RequestMappingHandlerMapping</code>&#x5B9E;&#x4F8B;&#xFF0C;&#x800C;&#x5339;&#x914D;&#x5230;&#x7684;<code>handlerMaping</code>&#x5B9E;&#x4F8B;&#x5185;<code>interceptors</code>&#x5217;&#x8868;&#x4E3A;&#x7A7A;&#xFF0C;&#x6240;&#x4EE5;&#x65E0;&#x6CD5;&#x4F7F;&#x5F97;&#x62E6;&#x622A;&#x5668;&#x751F;&#x6548;&#x3002;</p><a id="more"></a><h3 id="&#x8FFD;&#x8E2A;&#x95EE;&#x9898;"><a href="#&#x8FFD;&#x8E2A;&#x95EE;&#x9898;" class="headerlink" title="&#x8FFD;&#x8E2A;&#x95EE;&#x9898;"></a>&#x8FFD;&#x8E2A;&#x95EE;&#x9898;</h3><p>&#x4E3A;&#x4EC0;&#x4E48;&#x5B58;&#x5728;&#x4E24;&#x4E2A;<code>handlerMapping</code>&#x5B9E;&#x4F8B;&#xFF1F;</p><h4 id="&#x8DEF;&#x7531;&#x6620;&#x5C04;&#x5173;&#x7CFB;&#x521D;&#x59CB;&#x5316;&#x63A2;&#x7A76;"><a href="#&#x8DEF;&#x7531;&#x6620;&#x5C04;&#x5173;&#x7CFB;&#x521D;&#x59CB;&#x5316;&#x63A2;&#x7A76;" class="headerlink" title="&#x8DEF;&#x7531;&#x6620;&#x5C04;&#x5173;&#x7CFB;&#x521D;&#x59CB;&#x5316;&#x63A2;&#x7A76;"></a>&#x8DEF;&#x7531;&#x6620;&#x5C04;&#x5173;&#x7CFB;&#x521D;&#x59CB;&#x5316;&#x63A2;&#x7A76;</h4><p>&#x5148;&#x770B;&#x4E00;&#x4E0B;<code>handlerMapping</code>&#x662F;&#x4EC0;&#x4E48;&#x65F6;&#x5019;&#x521D;&#x59CB;&#x5316;&#x7684;&#x3002;<br>&#x5728;<code>DispatcherServelt</code>&#x7C7B;&#x91CC;&#xFF0C;&#x5728;&#x5237;&#x65B0;&#x5E94;&#x7528;&#x4E0A;&#x4E0B;&#x6587;&#xFF08;<code>onRefresh</code>&#xFF09;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x65B9;&#x6CD5;<code>initStrategies</code>&#x4F1A;&#x6267;&#x884C;&#xFF0C;&#x5982;&#x4E0B;&#x4EE3;&#x7801;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">initStrategies</span><span class="params">(ApplicationContext context)</span> </span>{</span><br><span class="line">    initMultipartResolver(context);</span><br><span class="line">    initLocaleResolver(context);</span><br><span class="line">    initThemeResolver(context);</span><br><span class="line">    initHandlerMappings(context);</span><br><span class="line">    initHandlerAdapters(context);</span><br><span class="line">    initHandlerExceptionResolvers(context);</span><br><span class="line">    initRequestToViewNameTranslator(context);</span><br><span class="line">    initViewResolvers(context);</span><br><span class="line">    initFlashMapManager(context);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x91CD;&#x70B9;&#x5728;&#x4E8E;<code>initHandlerMappings</code>&#x65B9;&#x6CD5;&#xFF0C;&#x5728;&#x8FD9;&#x4E2A;&#x65B9;&#x6CD5;&#x91CC;&#x9762;&#x521D;&#x59CB;&#x5316;&#x4E86;<code>handlerMapping</code>&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">initHandlerMappings</span><span class="params">(ApplicationContext context)</span> </span>{</span><br><span class="line">    <span class="keyword">this</span>.handlerMappings = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x662F;&#x5426;&#x68C0;&#x6D4B;&#x6240;&#x6709;&#x7684;&#x6620;&#x5C04;</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">this</span>.detectAllHandlerMappings) {</span><br><span class="line">        <span class="comment">// &#x67E5;&#x627E;&#x4E0A;&#x4E0B;&#x6587;&#x7684;&#x6240;&#x6709;HandlerMapping&#x5B9E;&#x4F8B;</span></span><br><span class="line">        Map&lt;String, HandlerMapping&gt; matchingBeans =</span><br><span class="line">                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, <span class="keyword">true</span>, <span class="keyword">false</span>);</span><br><span class="line">        <span class="keyword">if</span> (!matchingBeans.isEmpty()) {</span><br><span class="line">            <span class="keyword">this</span>.handlerMappings = <span class="keyword">new</span> ArrayList&lt;HandlerMapping&gt;(matchingBeans.values());</span><br><span class="line">            <span class="comment">// &#x4E0D;&#x4E3A;&#x7A7A;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#x8FDB;&#x884C;&#x6392;&#x5E8F;</span></span><br><span class="line">            AnnotationAwareOrderComparator.sort(<span class="keyword">this</span>.handlerMappings);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">else</span> {</span><br><span class="line">        <span class="comment">// &#x83B7;&#x53D6;&#x4E3B;&#x8981;&#x7684;handlerMapping</span></span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);</span><br><span class="line">            <span class="keyword">this</span>.handlerMappings = Collections.singletonList(hm);</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">catch</span> (NoSuchBeanDefinitionException ex) {</span><br><span class="line">            <span class="comment">// Ignore, we&apos;ll add a default HandlerMapping later.</span></span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x5982;&#x679C;&#x6CA1;&#x6709;handlerMapping&#xFF0C;&#x5219;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x9ED8;&#x8BA4;&#x7684;</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">this</span>.handlerMappings == <span class="keyword">null</span>) {</span><br><span class="line">        <span class="keyword">this</span>.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);</span><br><span class="line">        <span class="keyword">if</span> (logger.isDebugEnabled()) {</span><br><span class="line">            logger.debug(<span class="string">&quot;No HandlerMappings found in servlet &apos;&quot;</span> + getServletName() + <span class="string">&quot;&apos;: using default&quot;</span>);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p><code>detectAllHandlerMappings</code>&#x503C;&#x4E3A;<code>true</code>&#xFF0C;&#x5219;&#x4F1A;&#x4ECE;&#x4E0A;&#x6587;&#x4E2D;&#x67E5;&#x8BE2;&#x5B9E;&#x73B0;&#x4E86;<code>HandlerMapping</code>&#x63A5;&#x53E3;&#x7684;&#x6240;&#x6709;&#x5B50;&#x7C7B;&#x3002;&#x627E;&#x5230;<code>AbstractHandlerMethodMapping</code>&#x62BD;&#x8C61;&#x7C7B;&#xFF0C;&#x6240;&#x6709;&#x7684;&#x63A7;&#x5236;&#x5C42;&#x8DEF;&#x7531;&#x8DF3;&#x8F6C;&#xFF08;&#x4E3E;&#x4F8B;<code>@RequestMapping</code>&#xFF09;&#x90FD;&#x901A;&#x8FC7;<code>AbstractHandlerMethodMapping</code>&#x5B9E;&#x73B0;&#x3002;</p><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x5728;<code>AbstractHandlerMethodMapping</code>&#x7C7B;&#x5185;&#xFF0C;&#x5B9E;&#x73B0;&#x4E86;<code>InitializingBean</code>&#x63A5;&#x53E3;&#xFF1B;&#x540C;&#x65F6;&#x5728;<code>afterPropertiesSet</code>&#x65B9;&#x6CD5;&#x5185;&#xFF0C;&#x6267;&#x884C;&#x4E86;<code>initHandlerMethods</code>&#x65B9;&#x6CD5;&#x5E76;&#x521D;&#x59CB;&#x5316;&#x4E86;<code>handlerMapping</code>&#x3002;</p><h4 id="&#x7F6A;&#x9B41;&#x7978;&#x9996;&#x5B9A;&#x4F4D;"><a href="#&#x7F6A;&#x9B41;&#x7978;&#x9996;&#x5B9A;&#x4F4D;" class="headerlink" title="&#x7F6A;&#x9B41;&#x7978;&#x9996;&#x5B9A;&#x4F4D;"></a>&#x7F6A;&#x9B41;&#x7978;&#x9996;&#x5B9A;&#x4F4D;</h4><p>&#x5728;<code>initHandlerMethods</code>&#x65B9;&#x6CD5;&#x5185;&#x901A;&#x8FC7;<code>debug</code>&#x65AD;&#x70B9;&#x8FD0;&#x884C;&#x5E94;&#x7528;&#x540E;&#xFF0C;&#x53D1;&#x73B0;&#x5728;&#x8FD9;&#x91CC;&#x6267;&#x884C;&#x4E86;&#x4E24;&#x6B21;&#xFF1B;&#x5F88;&#x660E;&#x663E;&#xFF0C;&#x5E94;&#x7528;&#x5B9E;&#x4F8B;&#x5316;&#x4E86;&#x4E24;&#x6B21;<code>AbstractHandlerMethodMapping</code>&#x5B50;&#x7C7B;&#x3002;</p><p>&#x770B;&#x4E86;&#x4E0B;<code>AbstractHandlerMethodMapping</code>&#x7C7B;&#x7684;&#x6240;&#x6709;&#x5B50;&#x7C7B;&#xFF0C;&#x5217;&#x4E3E;&#x4E86;&#x4E0B;&#x5404;&#x81EA;&#x5B50;&#x7C7B;&#x7684;&#x5927;&#x81F4;&#x7528;&#x9014;&#xFF1A;</p><table><thead><tr><th>&#x5B50;&#x7C7B;&#x540D;</th><th>&#x7528;&#x9014;</th></tr></thead><tbody><tr><td>CloudFoundryEndpointHandlerMapping</td><td>Paas&#x5E73;&#x53F0;&#x8DEF;&#x7531;</td></tr><tr><td>EndpointHandlerMapping</td><td>&#x7BA1;&#x7406;/&#x5065;&#x5EB7;&#x68C0;&#x67E5;&#x8DEF;&#x7531;</td></tr><tr><td>RequestMappingHandlerMapping</td><td>&#x8BF7;&#x6C42;&#x6620;&#x5C04;&#x8DEF;&#x7531;</td></tr><tr><td>StaticRequestMappingHandlerMapping</td><td>&#x6D4B;&#x8BD5;&#x7528;&#x9759;&#x6001;&#x8DEF;&#x7531;</td></tr></tbody></table><p>&#x771F;&#x6B63;&#x9700;&#x8981;&#x5173;&#x6CE8;&#x7684;&#x662F;<code>RequestMappingHandlerMapping</code>&#x5B50;&#x7C7B;&#xFF0C;&#x770B;&#x4E86;&#x4E0B;&#x771F;&#x6B63;&#x7684;&#x8C03;&#x7528;&#x65B9;&#x53EA;&#x6709;<code>WebMvcAutoConfiguration</code>&#x914D;&#x7F6E;&#x7C7B;&#x5185;&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x5982;&#x4E0B;&#x4EE3;&#x7801;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="meta">@Primary</span></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> RequestMappingHandlerMapping <span class="title">requestMappingHandlerMapping</span><span class="params">()</span> </span>{</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">super</span>.requestMappingHandlerMapping();</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728;&#x8FD9;&#x91CC;&#xFF0C;&#x521B;&#x5EFA;&#x4E86;&#x4E00;&#x4E2A;&#x540D;&#x4E3A;<code>requestMappingHandlerMapping</code>&#x7684;<code>RequestMappingHandlerMapping</code>&#x5B9E;&#x4F8B;&#x7C7B;&#xFF0C;&#x5176;&#x4ED6;&#x5730;&#x65B9;&#x5E76;&#x672A;&#x8FDB;&#x884C;&#x76F8;&#x5173;&#x7684;&#x521B;&#x5EFA;&#x3002;&#x5728;&#x60F3;&#x5230;&#x8BF7;&#x6C42;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x5B58;&#x5728;&#x4E24;&#x4E2A;<code>RequestMappingHandlerMapping</code>&#x5B9E;&#x4F8B;&#xFF0C;&#x90A3;&#x4E48;&#x80AF;&#x5B9A;&#x6709;&#x5176;&#x4ED6;&#x5165;&#x53E3;&#x80FD;&#x591F;&#x521B;&#x5EFA;&#x65B0;&#x7684;&#x5B9E;&#x4F8B;&#x3002;</p><p>&#x7ECF;&#x8FC7;N&#x5C0F;&#x65F6;&#x7684;&#x6298;&#x817E;&#x67E5;&#x8BE2;&#xFF08;&#x8FC7;&#x7A0B;&#x4E0D;&#x582A;&#x56DE;&#x9996;&#xFF09;&#xFF0C;&#x7EC8;&#x4E8E;&#x53D1;&#x73B0;&#x662F;&#x5E94;&#x7528;&#x5185;&#x7684;<code>ImportResource</code>&#x5F15;&#x5165;&#x7684;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span>(scanBasePackages = {<span class="string">&quot;com.xxx&quot;</span>})</span><br><span class="line"><span class="meta">@ImportResource</span>(<span class="string">&quot;classpath*:spring/applicationContext.xml&quot;</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BootstrapApp</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line">        SpringApplication.run(BootstrapApp.class);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x4E0A;&#x8FF0;&#x4EE3;&#x7801;&#xFF0C;&#x5728;&#x5E94;&#x7528;&#x542F;&#x52A8;&#x7C7B;&#x4E0A;&#x52A0;&#x4E86;<code>@ImportResource(&quot;classpath*:spring/applicationContext.xml&quot;)</code>&#x3002;&#x8FD9;&#x4E2A;&#x5C31;&#x662F;&#x7F6A;&#x9B41;&#x7978;&#x9996;&#x3002;</p><h4 id="&#x539F;&#x56E0;&#x63A2;&#x7A76;"><a href="#&#x539F;&#x56E0;&#x63A2;&#x7A76;" class="headerlink" title="&#x539F;&#x56E0;&#x63A2;&#x7A76;"></a>&#x539F;&#x56E0;&#x63A2;&#x7A76;</h4><p>&#x4E3A;&#x4EC0;&#x4E48;<code>@ImportResource</code>&#x5728;&#x6CE8;&#x5165;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#x4F1A;&#x6CE8;&#x518C;&#x4E00;&#x4E2A;<code>RequestMappingHandlerMapping</code>&#x5B9E;&#x4F8B;&#xFF0C;&#x4E14;&#x4E3A;&#x5565;&#x8FD9;&#x4E2A;&#x5B9E;&#x4F8B;&#x6CA1;&#x6709;&#x88AB;<code>@Primary</code>&#x8986;&#x76D6;&#xFF1F;</p><p>&#x5B9A;&#x4F4D;&#x5230;<code>ConfigurationClassPostProcessor</code>&#x7C7B;&#xFF0C;&#x8FD9;&#x4E2A;&#x7C7B;&#x662F;&#x5BF9;&#x6240;&#x6709;&#x914D;&#x7F6E;&#x7C7B;&#x6587;&#x4EF6;&#x505A;&#x89E3;&#x6790;&#x3002;&#x5728;&#x65B9;&#x6CD5;<code>processConfigBeanDefinitions</code>&#x5185;&#x4F7F;&#x7528;<code>ConfigurationClassParser</code>&#x7C7B;&#x5177;&#x4F53;&#x6267;&#x884C;&#x89E3;&#x6790;&#x64CD;&#x4F5C;&#x3002;&#x5177;&#x4F53;&#x53EF;&#x4EE5;&#x770B;&#x8FD9;&#x7BC7;&#x6587;&#x7AE0;&#x3010;<a href="https://xuqiang.me/Spring-Bean&#x89E3;&#x6790;&#x5206;&#x6790;&#x8FC7;&#x7A0B;.html">Spring-Bean&#x89E3;&#x6790;&#x5206;&#x6790;&#x8FC7;&#x7A0B;</a>&#x3011;</p><p>&#x5728;&#x65B9;&#x6CD5;<code>doProcessConfigurationClass</code>&#x5185;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5904;&#x7406;&#x4EFB;&#x610F;@ImportResource&#x6CE8;&#x89E3;</span></span><br><span class="line"><span class="keyword">if</span> (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {</span><br><span class="line">    AnnotationAttributes importResource =</span><br><span class="line">            AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);</span><br><span class="line">    <span class="comment">// &#x83B7;&#x53D6;&#x6CE8;&#x89E3;&#x4E0A;&#x7684;&#x8D44;&#x6E90;&#x4F4D;&#x7F6E;</span></span><br><span class="line">    String[] resources = importResource.getStringArray(<span class="string">&quot;locations&quot;</span>);</span><br><span class="line">    <span class="comment">// &#x83B7;&#x53D6;&#x8D44;&#x6E90;&#x7684;&#x89E3;&#x91CA;&#x5668;</span></span><br><span class="line">    Class&lt;? extends BeanDefinitionReader&gt; readerClass = importResource.getClass(<span class="string">&quot;reader&quot;</span>);</span><br><span class="line">    <span class="keyword">for</span> (String resource : resources) {</span><br><span class="line">        String resolvedResource = <span class="keyword">this</span>.environment.resolveRequiredPlaceholders(resource);</span><br><span class="line">        <span class="comment">// &#x5C06;&#x8D44;&#x6E90;&#x4F4D;&#x7F6E;&#x548C;&#x5BF9;&#x5E94;&#x7684;&#x89E3;&#x91CA;&#x5668;&#x653E;&#x5165;&#x914D;&#x7F6E;&#x6587;&#x4EF6;&#x5B9E;&#x4F8B;&#x5185;</span></span><br><span class="line">        configClass.addImportedResource(resolvedResource, readerClass);</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x89E3;&#x6790;&#x4E86;<code>@ImportResource</code>&#xFF0C;&#x5E76;&#x628A;&#x5C5E;&#x6027;&#x6CE8;&#x5165;&#x5230;&#x914D;&#x7F6E;&#x6587;&#x4EF6;&#x7C7B;&#x5185;&#xFF0C;&#x5728;&#x8FD9;&#x91CC;&#x53EA;&#x662F;&#x4E00;&#x4E2A;&#x6807;&#x8BB0;&#xFF0C;&#x5E76;&#x6CA1;&#x771F;&#x6B63;&#x5904;&#x7406;&#x3002;</p><p>&#x89E3;&#x6790;&#x5B8C;&#x6210;&#x540E;&#xFF0C;<code>ConfigurationClassBeanDefinitionReader</code>&#x7C7B;&#x4F1A;&#x8BFB;&#x53D6;&#x914D;&#x7F6E;&#x7C7B;&#x6587;&#x4EF6;&#xFF0C;&#x5E76;&#x52A0;&#x8F7D;&#x6240;&#x6709;&#x7684;<code>beanDefinition</code>&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x8BFB;&#x53D6;&#x8D44;&#x6E90;&#x5185;&#x5BB9;&#x5E76;&#x4E14;&#x6839;&#x636E;&#x5185;&#x5BB9;&#x521B;&#x5EFA;bean&#x5B9A;&#x4E49;</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">this</span>.reader == <span class="keyword">null</span>) {</span><br><span class="line">    <span class="keyword">this</span>.reader = <span class="keyword">new</span> ConfigurationClassBeanDefinitionReader(</span><br><span class="line">            registry, <span class="keyword">this</span>.sourceExtractor, <span class="keyword">this</span>.resourceLoader, <span class="keyword">this</span>.environment,</span><br><span class="line">            <span class="keyword">this</span>.importBeanNameGenerator, parser.getImportRegistry());</span><br><span class="line">}</span><br><span class="line"><span class="keyword">this</span>.reader.loadBeanDefinitions(configClasses);</span><br></pre></td></tr></tbody></table></figure><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">loadBeanDefinitionsForConfigurationClass</span><span class="params">(ConfigurationClass configClass,</span></span></span><br><span class="line"><span class="function"><span class="params">TrackedConditionEvaluator trackedConditionEvaluator)</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (trackedConditionEvaluator.shouldSkip(configClass)) {</span><br><span class="line">        String beanName = configClass.getBeanName();</span><br><span class="line">        <span class="keyword">if</span> (StringUtils.hasLength(beanName) &amp;&amp; <span class="keyword">this</span>.registry.containsBeanDefinition(beanName)) {</span><br><span class="line">            <span class="keyword">this</span>.registry.removeBeanDefinition(beanName);</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">this</span>.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (configClass.isImported()) {</span><br><span class="line">        registerBeanDefinitionForImportedConfigurationClass(configClass);</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">for</span> (BeanMethod beanMethod : configClass.getBeanMethods()) {</span><br><span class="line">        loadBeanDefinitionsForBeanMethod(beanMethod);</span><br><span class="line">    }</span><br><span class="line">    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());</span><br><span class="line">    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728;&#x8FD9;&#x91CC;&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x5BF9;&#x89E3;&#x6790;&#x7684;&#x505A;&#x4E86;&#x5904;&#x7406;&#xFF0C;&#x91CD;&#x70B9;&#x5173;&#x6CE8;<code>loadBeanDefinitionsFromImportedResources</code>&#x65B9;&#x6CD5;&#xFF0C;&#x8FD9;&#x4E2A;&#x65B9;&#x6CD5;&#x5BF9;&#x5F15;&#x5165;&#x7684;&#x8D44;&#x6E90;&#x505A;&#x4E86;&#x89E3;&#x6790;&#x5E76;&#x6CE8;&#x518C;&#x4E3A;<code>beanDefinition</code>&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">loadBeanDefinitionsFromImportedResources</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">Map&lt;String, Class&lt;? extends BeanDefinitionReader&gt;&gt; importedResources)</span> </span>{</span><br><span class="line"></span><br><span class="line">    Map&lt;Class&lt;?&gt;, BeanDefinitionReader&gt; readerInstanceCache = <span class="keyword">new</span> HashMap&lt;Class&lt;?&gt;, BeanDefinitionReader&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (Map.Entry&lt;String, Class&lt;? extends BeanDefinitionReader&gt;&gt; entry : importedResources.entrySet()) {</span><br><span class="line">        String resource = entry.getKey();</span><br><span class="line">        Class&lt;? extends BeanDefinitionReader&gt; readerClass = entry.getValue();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// Default reader selection necessary?</span></span><br><span class="line">        <span class="keyword">if</span> (BeanDefinitionReader.class == readerClass) {</span><br><span class="line">            <span class="keyword">if</span> (StringUtils.endsWithIgnoreCase(resource, <span class="string">&quot;.groovy&quot;</span>)) {</span><br><span class="line">                <span class="comment">// .groovy&#x811A;&#x672C;&#x6587;&#x4EF6;&#x89E3;&#x6790;</span></span><br><span class="line">                readerClass = GroovyBeanDefinitionReader.class;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span> {</span><br><span class="line">                <span class="comment">// &#x4E3B;&#x8981;&#x5BF9;&#x4E8E;.xml&#x6587;&#x4EF6;&#x7684;&#x89E3;&#x6790;&#xFF0C;&#x4E5F;&#x53EF;&#x4EE5;&#x89E3;&#x6790;&#x5176;&#x4ED6;&#x6587;&#x4EF6;</span></span><br><span class="line">                readerClass = XmlBeanDefinitionReader.class;</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &#x901A;&#x8FC7;readerClass&#x83B7;&#x53D6;&#x5177;&#x4F53;&#x7684;reader&#x5B9E;&#x4F8B;</span></span><br><span class="line">        BeanDefinitionReader reader = readerInstanceCache.get(readerClass);</span><br><span class="line">        <span class="keyword">if</span> (reader == <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">try</span> {</span><br><span class="line">                <span class="comment">// &#x5982;&#x679C;&#x4E0D;&#x5B58;&#x5728;&#x5219;&#x5B9E;&#x4F8B;&#x5316;reader</span></span><br><span class="line">                reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(<span class="keyword">this</span>.registry);</span><br><span class="line">                <span class="comment">// Delegate the current ResourceLoader to it if possible</span></span><br><span class="line">                <span class="keyword">if</span> (reader <span class="keyword">instanceof</span> AbstractBeanDefinitionReader) {</span><br><span class="line">                    AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);</span><br><span class="line">                    abdr.setResourceLoader(<span class="keyword">this</span>.resourceLoader);</span><br><span class="line">                    abdr.setEnvironment(<span class="keyword">this</span>.environment);</span><br><span class="line">                }</span><br><span class="line">                readerInstanceCache.put(readerClass, reader);</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">catch</span> (Throwable ex) {</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException(</span><br><span class="line">                        <span class="string">&quot;Could not instantiate BeanDefinitionReader class [&quot;</span> + readerClass.getName() + <span class="string">&quot;]&quot;</span>);</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &#x901A;&#x8FC7;reader&#x8BFB;&#x53D6;bean&#x5B9A;&#x4E49;</span></span><br><span class="line">        reader.loadBeanDefinitions(resource);</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728;&#x8FD9;&#x4E2A;&#x7C7B;&#x91CC;&#x9762;&#xFF0C;<code>reader</code>&#x6839;&#x636E;&#x5BFC;&#x5165;&#x8D44;&#x6E90;&#x6587;&#x4EF6;&#x683C;&#x5F0F;&#x5B9E;&#x4F8B;&#x5316;&#x540E;&#xFF0C;&#x901A;&#x8FC7;<code>reader</code>&#x6765;&#x8BFB;&#x53D6;<code>bean</code>&#x5B9A;&#x4E49;&#x3002;&#x50CF;&#x6211;&#x4EEC;&#x8FD9;&#x91CC;&#x5BFC;&#x5165;&#x7684;&#x662F;xml&#x8D44;&#x6E90;&#x6587;&#x4EF6;&#xFF0C;&#x5219;&#x4F1A;&#x751F;&#x6210;<code>XmlBeanDefinitionReader</code>&#x5B9E;&#x4F8B;&#x3002;</p><p>&#x5728;&#x8FD9;&#x4E2A;&#x5B9E;&#x4F8B;&#x5BF9;&#x4E8E;&#x5143;&#x7D20;&#x7684;&#x5177;&#x4F53;&#x89E3;&#x6790;&#x91CC;&#xFF0C;&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x7B54;&#x6848;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> BeanDefinition <span class="title">parse</span><span class="params">(Element element, ParserContext parserContext)</span> </span>{</span><br><span class="line">    Object source = parserContext.extractSource(element);</span><br><span class="line">    XmlReaderContext readerContext = parserContext.getReaderContext();</span><br><span class="line"></span><br><span class="line">    CompositeComponentDefinition compDefinition = <span class="keyword">new</span> CompositeComponentDefinition(element.getTagName(), source);</span><br><span class="line">    parserContext.pushContainingComponent(compDefinition);</span><br><span class="line"></span><br><span class="line">    RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x521B;&#x5EFA;&#x4E86;&#x4E00;&#x4E2A;HanderMapping&#x7684;bean&#x5B9A;&#x4E49;</span></span><br><span class="line">    RootBeanDefinition handlerMappingDef = <span class="keyword">new</span> RootBeanDefinition(RequestMappingHandlerMapping.class);</span><br><span class="line">    handlerMappingDef.setSource(source);</span><br><span class="line">    handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);</span><br><span class="line">    handlerMappingDef.getPropertyValues().add(<span class="string">&quot;order&quot;</span>, <span class="number">0</span>);</span><br><span class="line">    handlerMappingDef.getPropertyValues().add(<span class="string">&quot;contentNegotiationManager&quot;</span>, contentNegotiationManager);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (element.hasAttribute(<span class="string">&quot;enable-matrix-variables&quot;</span>)) {</span><br><span class="line">        Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute(<span class="string">&quot;enable-matrix-variables&quot;</span>));</span><br><span class="line">        handlerMappingDef.getPropertyValues().add(<span class="string">&quot;removeSemicolonContent&quot;</span>, !enableMatrixVariables);</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (element.hasAttribute(<span class="string">&quot;enableMatrixVariables&quot;</span>)) {</span><br><span class="line">        Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute(<span class="string">&quot;enableMatrixVariables&quot;</span>));</span><br><span class="line">        handlerMappingDef.getPropertyValues().add(<span class="string">&quot;removeSemicolonContent&quot;</span>, !enableMatrixVariables);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x5728;&#x8FD9;&#x91CC;&#x6CE8;&#x518C;handerMapping&#x7684;bean&#x5B9A;&#x4E49;</span></span><br><span class="line">    configurePathMatchingProperties(handlerMappingDef, element, parserContext);</span><br><span class="line">    readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ....&#x5176;&#x4ED6;&#x4EE3;&#x7801;&#x7701;&#x7565;</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#xFF0C;&#x5728;&#x8FD9;&#x6BB5;&#x4EE3;&#x7801;&#x5185;&#x521B;&#x5EFA;&#x4E86;&#x540D;&#x4E3A;<code>org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping</code>&#x7684;<code>bean</code>&#x5B9A;&#x4E49;&#x3002;</p><p>&#x800C;<code>WebMvcAutoConfiguration</code>&#x521B;&#x5EFA;&#x7684;<code>handlerMapping&#x7684;bean</code>&#x5B9A;&#x4E49;&#x540D;&#x4E3A;<code>requestMappingHandlerMapping</code>&#x3002;</p><p>&#x8FD9;&#x4E2A;&#x5BFC;&#x81F4;&#x7684;&#x540E;&#x679C;&#x5C31;&#x662F;&#xFF0C;IOC&#x5BB9;&#x5668;&#x5185;&#x5B58;&#x5728;&#x4E24;&#x4E2A;<code>RequestMapping</code>&#x3002;</p><h3 id="&#x89E3;&#x51B3;&#x95EE;&#x9898;"><a href="#&#x89E3;&#x51B3;&#x95EE;&#x9898;" class="headerlink" title="&#x89E3;&#x51B3;&#x95EE;&#x9898;"></a>&#x89E3;&#x51B3;&#x95EE;&#x9898;</h3><p>&#x6709;&#x5982;&#x4E0B;&#x4E09;&#x79CD;&#x65B9;&#x6CD5;&#xFF1A;</p><ol><li>&#x5B9A;&#x4E49;<code>RequestMapping</code>&#x7684;&#x987A;&#x5E8F;&#xFF0C;&#x4F46;&#x662F;&#x4E24;&#x8005;&#x90FD;&#x662F;&#x7CFB;&#x7EDF;&#x8F7D;&#x5165;&#xFF0C;&#x65E0;&#x6CD5;&#x4FEE;&#x6539;&#x5B9A;&#x4E49;&#x3002;</li><li>&#x5C06;<code>xml</code>&#x7684;&#x914D;&#x7F6E;&#x66F4;&#x6539;&#x4E3A;&#x6CE8;&#x89E3;&#x914D;&#x7F6E;&#xFF0C;&#x8FD9;&#x6837;&#x5C31;&#x53EF;&#x4EE5;&#x907F;&#x514D;&#x4E0A;&#x8FF0;&#x7684;&#x95EE;&#x9898;</li><li>&#x8BBE;&#x7F6E;<code>detectAllHandlerMappings</code>&#x503C;&#x4E3A;<code>false</code></li></ol><h3 id="&#x603B;&#x7ED3;"><a href="#&#x603B;&#x7ED3;" class="headerlink" title="&#x603B;&#x7ED3;"></a>&#x603B;&#x7ED3;</h3><p>&#x5728;&#x4E0D;&#x4E86;&#x89E3;&#x5185;&#x90E8;&#x673A;&#x5236;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#xFF0C;&#x771F;&#x7684;&#x4E0D;&#x80FD;&#x6EE5;&#x7528;&#x4E00;&#x4E9B;&#x914D;&#x7F6E;&#xFF0C;&#x56E0;&#x4E3A;&#x5F80;&#x5F80;&#x4F1A;&#x9020;&#x6210;&#x4E00;&#x4E9B;&#x51FA;&#x4EBA;&#x610F;&#x6599;&#x7684;&#x4E8B;&#x60C5;&#x3002;</p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;&lt;code&gt;SpringBoot&lt;/code&gt;项目增加&lt;code&gt;Spring&lt;/code&gt;拦截器，但是却发现没有生效；&lt;code&gt;debug DispatchServelt&lt;/code&gt;，发现在查找&lt;code&gt;handler&lt;/code&gt;的时候，由于存在多个&lt;code&gt;RequestMappingHandlerMapping&lt;/code&gt;实例，而匹配到的&lt;code&gt;handlerMaping&lt;/code&gt;实例内&lt;code&gt;interceptors&lt;/code&gt;列表为空，所以无法使得拦截器生效。&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="Spring" scheme="https://xuqiang.me/categories/Java/Spring/"/>
    
      <category term="SpringSources" scheme="https://xuqiang.me/categories/Java/Spring/SpringSources/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="bean" scheme="https://xuqiang.me/tags/bean/"/>
    
      <category term="spring" scheme="https://xuqiang.me/tags/spring/"/>
    
      <category term="import" scheme="https://xuqiang.me/tags/import/"/>
    
      <category term="interceptor" scheme="https://xuqiang.me/tags/interceptor/"/>
    
  </entry>
  
  <entry>
    <title>构建C远程开发环境</title>
    <link href="https://xuqiang.me/build-c-remote-compile-env.html"/>
    <id>https://xuqiang.me/build-c-remote-compile-env.html</id>
    <published>2019-08-17T16:37:03.000Z</published>
    <updated>2019-08-17T18:09:24.140Z</updated>
    
    <content type="html"><![CDATA[<h2 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h2><p>&#x6700;&#x8FD1;&#x5728;&#x5B66;&#x4E60;Linux&#x5185;&#x6838;&#x4F53;&#x7CFB;&#x77E5;&#x8BC6;&#xFF0C;&#x9700;&#x8981;C&#x7684;&#x4E00;&#x4E2A;&#x7F16;&#x8BD1;&#x73AF;&#x5883;&#x3002;&#x4F46;&#x662F;&#x7531;&#x4E8E;&#x7B14;&#x8005;&#x4F7F;&#x7528;&#x73AF;&#x5883;&#x4E3A;MacOS&#xFF0C;&#x5E76;&#x975E;&#x4F7F;&#x7528;&#x7684;Linux&#x4F53;&#x7CFB;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#xFF0C;&#x5728;&#x8FDB;&#x884C;&#x5185;&#x6838;&#x7F16;&#x7A0B;&#x7684;&#x65F6;&#x5019;&#x5C31;&#x65E0;&#x6CD5;&#x8C03;&#x7528;linux&#x7CFB;&#x7EDF;&#x51FD;&#x6570;&#xFF1B;&#x7136;&#x540E;&#x5728;&#x6298;&#x817E;&#x4E86;&#x4E00;&#x904D;ubuntu&#x865A;&#x62DF;&#x673A;&#x3001;&#x5B9E;&#x4F53;&#x673A;&#xFF08;&#x663E;&#x5361;&#x95EE;&#x9898;&#xFF09;&#x540E;&#xFF0C;&#x610F;&#x5916;&#x53D1;&#x73B0;&#x4E86;CLion&#x7684;&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x529F;&#x80FD;&#x3002;</p><a id="more"></a><h2 id="&#x6784;&#x5EFA;&#x8FDC;&#x7A0B;&#x7F16;&#x8BD1;&#x73AF;&#x5883;"><a href="#&#x6784;&#x5EFA;&#x8FDC;&#x7A0B;&#x7F16;&#x8BD1;&#x73AF;&#x5883;" class="headerlink" title="&#x6784;&#x5EFA;&#x8FDC;&#x7A0B;&#x7F16;&#x8BD1;&#x73AF;&#x5883;"></a>&#x6784;&#x5EFA;&#x8FDC;&#x7A0B;&#x7F16;&#x8BD1;&#x73AF;&#x5883;</h2><p>CLion&#x7684;&#x8FDC;&#x7A0B;&#x8FD0;&#x884C;&#x73AF;&#x5883;&#x9700;&#x8981;&#x5982;&#x4E0B;&#x7A0B;&#x5E8F;&#xFF1A;</p><ul><li>rsync(for macos or linux locally)</li><li>sftp &amp; gzip(for windows locally)</li><li>CMake(2.18.x-3.14.x)</li><li>Make</li><li>C compiler</li><li>C++ Compiler</li><li>GDB(7.x-8.x)</li></ul><p>&#x5B89;&#x5168;&#x5B8C;&#x6210;&#x540E;&#xFF0C;&#x914D;&#x7F6E;&#x5982;&#x4E0B;&#xFF1A;</p><ul><li><p>&#x914D;&#x7F6E;&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#xFF1A;<br><img src="https://static.xuqiang.me/public/images/165707.png" alt="&#x914D;&#x7F6E;remote"></p></li><li><p>&#x914D;&#x7F6E;&#x8BA4;&#x8BC1;&#xFF1A;<br><img src="https://static.xuqiang.me/public/images/165613.png" alt="&#x914D;&#x7F6E;ssh"></p></li></ul><p>&#x5B8C;&#x6210;&#x914D;&#x7F6E;&#x540E;&#xFF0C;&#x4F1A;&#x81EA;&#x52A8;&#x540C;&#x6B65;&#x4E00;&#x6B21;&#x6E90;&#x6587;&#x4EF6;&#x5230;/tmp&#x76EE;&#x5F55;&#x4E0B;&#x7684;&#x67D0;&#x4E2A;&#x4E34;&#x65F6;&#x6587;&#x4EF6;&#x5939;&#x5185;&#x3002;</p><p><strong>&#x6CE8;&#x610F;</strong>&#xFF1A;&#x5982;&#x679C;&#x9700;&#x8981;&#x91CD;&#x65B0;&#x540C;&#x6B65;&#xFF0C;&#x53EA;&#x9700;&#x8981;&#x53F3;&#x952E;&#x9879;&#x76EE;&#xFF0C;&#x9009;&#x62E9;<code>Reload CMake Project</code>&#x5373;&#x53EF;&#x3002;</p><h2 id="&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x539F;&#x7406;"><a href="#&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x539F;&#x7406;" class="headerlink" title="&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x539F;&#x7406;"></a>&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x539F;&#x7406;</h2><p><img src="https://static.xuqiang.me/public/images/180026.png" alt="&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x539F;&#x7406;"></p><p>CLion&#x7684;&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x57FA;&#x4E8E;&#x6587;&#x4EF6;&#x4F20;&#x8F93;&#x4EE5;&#x53CA;GDB&#x670D;&#x52A1;&#xFF1A;</p><ol><li>&#x4E0A;&#x4F20;&#x9879;&#x76EE;&#x76EE;&#x5F55;&#x81F3;&#x8FDC;&#x7A0B;&#x670D;&#x52A1;&#x5668;&#x3010;mac&#x6216;&#x8005;linux&#x4F7F;&#x7528;rsync&#xFF0C;windows&#x4F7F;&#x7528;sftp&#x548C;gzip&#x540C;&#x6B65;&#x7A0B;&#x5E8F;&#x3011;</li><li>&#x8FDC;&#x7AEF;&#x68C0;&#x7D22;&#x6240;&#x6709;&#x5934;&#x6587;&#x4EF6;&#xFF0C;&#x5E76;&#x4E0B;&#x8F7D;&#x7F13;&#x5B58;&#x5230;&#x672C;&#x5730;&#x7684;<code>.remote/${ip}_${port}/</code>&#x6587;&#x4EF6;&#x5939;&#x4E0B;</li><li>Debug&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x540C;&#x6B65;Debug&#x6807;&#x8BB0;&#x6587;&#x4EF6;&#x548C;&#x4E8C;&#x8FDB;&#x5236;&#x6587;&#x4EF6;&#x3010;&#x5177;&#x4F53;&#x5355;&#x70B9;&#x8C03;&#x8BD5;&#x6B65;&#x9AA4;&#x672A;&#x77E5;&#xFF0C;TODO&#x3011;</li></ol><h2 id="&#x9644;&#x5F55;"><a href="#&#x9644;&#x5F55;" class="headerlink" title="&#x9644;&#x5F55;"></a>&#x9644;&#x5F55;</h2><ul><li><a href="https://www.youtube.com/watch?v=g1zPcja3zAU" target="_blank" rel="noopener">CLion&#x8FDC;&#x7A0B;&#x539F;&#x7406;&#x8BB2;&#x89E3;</a></li></ul><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h2 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h2&gt;&lt;p&gt;最近在学习Linux内核体系知识，需要C的一个编译环境。但是由于笔者使用环境为MacOS，并非使用的Linux体系操作系统，在进行内核编程的时候就无法调用linux系统函数；然后在折腾了一遍ubuntu虚拟机、实体机（显卡问题）后，意外发现了CLion的远程调试功能。&lt;/p&gt;
    
    </summary>
    
      <category term="C" scheme="https://xuqiang.me/categories/C/"/>
    
      <category term="CLion" scheme="https://xuqiang.me/categories/C/CLion/"/>
    
    
      <category term="c" scheme="https://xuqiang.me/tags/c/"/>
    
      <category term="remote" scheme="https://xuqiang.me/tags/remote/"/>
    
      <category term="debug" scheme="https://xuqiang.me/tags/debug/"/>
    
      <category term="gdb" scheme="https://xuqiang.me/tags/gdb/"/>
    
  </entry>
  
  <entry>
    <title>在IDEA中DEBUG Javac源码</title>
    <link href="https://xuqiang.me/2019-07-13-debug-javac-in-idea.html"/>
    <id>https://xuqiang.me/2019-07-13-debug-javac-in-idea.html</id>
    <published>2019-07-13T06:15:57.000Z</published>
    <updated>2019-07-13T07:14:39.505Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x5728;&#x505A;JSR269&#x7684;&#x6DF1;&#x5EA6;&#x89E3;&#x6790;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x9700;&#x8981;&#x5BF9;javac&#x7684;&#x6E90;&#x4EE3;&#x7801;&#x8FDB;&#x884C;&#x5355;&#x6B65;&#x8C03;&#x8BD5;&#x5E76;&#x8DDF;&#x8E2A;&#x3002;&#x56E0;&#x6B64;&#x5728;&#x8FD9;&#x91CC;&#x8BB0;&#x5F55;&#x4E0B;&#x5177;&#x4F53;&#x7684;&#x8C03;&#x8BD5;&#x6B65;&#x9AA4;&#x3002;</p><p>&#x8C03;&#x8BD5;&#x73AF;&#x5883;&#xFF1A;<br>OS: MacOS 10.14.5<br>JDK&#xFF1A;JDK_1.8<br>IDEA: IntelliJ IDEA 2019.1.3</p><a id="more"></a><h3 id="&#x4E0B;&#x8F7D;Javac&#x6E90;&#x7801;"><a href="#&#x4E0B;&#x8F7D;Javac&#x6E90;&#x7801;" class="headerlink" title="&#x4E0B;&#x8F7D;Javac&#x6E90;&#x7801;"></a>&#x4E0B;&#x8F7D;Javac&#x6E90;&#x7801;</h3><p>&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x7528;JDK&#x7684;github&#x955C;&#x50CF;&#x4ED3;&#x5E93;&#x5904;&#x4E0B;&#x8F7D;&#xFF0C;<a href="https://github.com/openjdk/jdk" target="_blank" rel="noopener">&#x94FE;&#x63A5;&#x5728;&#x6B64;&#x5904;</a>&#xFF1B;&#x4E0B;&#x8F7D;&#x5B8C;&#x6210;&#x540E;checkout tag&#x81F3;&#xFF1A;jdk8-b120&#x3002;&#x5982;&#x679C;&#x672C;&#x5730;&#x5B89;&#x88C5;&#x7684;&#x662F;Oracle JDK&#xFF0C;&#x5219;&#x6E90;&#x4EE3;&#x7801;&#x53EF;&#x80FD;&#x4F1A;&#x6709;&#x4E9B;&#x7EC6;&#x5FAE;&#x5DEE;&#x522B;&#x3002;</p><h3 id="&#x4FEE;&#x6539;IDEA&#x76D1;&#x542C;&#x7AEF;&#x53E3;"><a href="#&#x4FEE;&#x6539;IDEA&#x76D1;&#x542C;&#x7AEF;&#x53E3;" class="headerlink" title="&#x4FEE;&#x6539;IDEA&#x76D1;&#x542C;&#x7AEF;&#x53E3;"></a>&#x4FEE;&#x6539;IDEA&#x76D1;&#x542C;&#x7AEF;&#x53E3;</h3><p>Help -&gt; Edit Custom VM Options</p><p>&#x5728;&#x6700;&#x540E;&#x589E;&#x52A0;&#x5982;&#x4E0B;&#x4EE3;&#x7801;&#xFF1A;<br></p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-Dcompiler.process.debug.port=12346</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x589E;&#x52A0;<code>port</code>&#x540E;&#xFF0C;idea&#x5728;&#x7F16;&#x8BD1;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x4F1A;&#x81EA;&#x52A8;&#x5F00;&#x542F;&#x76D1;&#x542C;&#x7AEF;&#x53E3;<code>12346</code>&#x3002;</p><p><strong>&#x4FEE;&#x6539;&#x5B8C;&#x6210;&#x540E;&#x8BB0;&#x5F97;&#x9700;&#x8981;&#x91CD;&#x542F;IDEA</strong></p><h3 id="&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x7A0B;&#x5E8F;"><a href="#&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x7A0B;&#x5E8F;" class="headerlink" title="&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x7A0B;&#x5E8F;"></a>&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x7A0B;&#x5E8F;</h3><p><img src="https://static.xuqiang.me/public/images/065854.jpg" alt="&#x8C03;&#x8BD5;&#x7A0B;&#x5E8F;"></p><p>&#x5982;&#x4E0A;&#x56FE;&#xFF0C;<code>Host</code>&#x8BBE;&#x7F6E;&#x4E3A;<code>localhost</code>&#xFF0C;<code>Port</code>&#x8BBE;&#x7F6E;&#x4E3A;<code>12346</code>&#x3002;</p><h3 id="&#x542F;&#x7528;&#x7F16;&#x8BD1;&#x8C03;&#x8BD5;"><a href="#&#x542F;&#x7528;&#x7F16;&#x8BD1;&#x8C03;&#x8BD5;" class="headerlink" title="&#x542F;&#x7528;&#x7F16;&#x8BD1;&#x8C03;&#x8BD5;"></a>&#x542F;&#x7528;&#x7F16;&#x8BD1;&#x8C03;&#x8BD5;</h3><p>&#x9ED8;&#x8BA4;IDEA&#x4F1A;&#x7981;&#x7528;&#x7F16;&#x8BD1;&#x8C03;&#x8BD5;&#xFF0C;&#x8FD9;&#x91CC;&#x9700;&#x8981;&#x5F00;&#x542F;&#x4E00;&#x4E2A;&#x5F00;&#x5173;&#xFF0C;&#x4EE5;&#x6B64;&#x8BA9;IDEA&#x5728;&#x7F16;&#x8BD1;&#x4E4B;&#x524D;&#x7B49;&#x5F85;&#x8C03;&#x8BD5;&#x7A0B;&#x5E8F;&#x7684;&#x94FE;&#x63A5;&#x3002;&#x5E76;&#x4E14;&#xFF0C;<strong>&#x8FD9;&#x4E2A;&#x914D;&#x7F6E;&#x5728;IDEA&#x91CD;&#x542F;&#x540E;&#x4F1A;&#x5931;&#x6548;</strong>&#x3002;</p><p>&#x53CC;&#x51FB;<code>Shift</code>&#xFF0C;&#x6253;&#x5F00;&#x5E73;&#x5E38;&#x641C;&#x7D22;&#x7C7B;&#x7684;&#x754C;&#x9762;&#xFF0C;&#x8F93;&#x5165;<code>debug build process</code>&#xFF0C;&#x5982;&#x4E0B;&#x56FE;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/070309.jpg" alt="&#x672A;&#x542F;&#x7528;"></p><p>&#x70B9;&#x51FB;&#x542F;&#x7528;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/070339.png" alt="&#x5DF2;&#x542F;&#x7528;"></p><h3 id="&#x6D4B;&#x8BD5;"><a href="#&#x6D4B;&#x8BD5;" class="headerlink" title="&#x6D4B;&#x8BD5;"></a>&#x6D4B;&#x8BD5;</h3><p>&#x70B9;&#x51FB;&#x7F16;&#x8BD1;&#xFF0C;IDEA&#x72B6;&#x6001;&#x680F;&#x4F1A;&#x51FA;&#x73B0;&#x5982;&#x4E0B;&#x63D0;&#x793A;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/070425.jpg" alt="&#x7B49;&#x5F85;"></p><p>&#x8FD9;&#x4E2A;&#x5C31;&#x4EE3;&#x8868;<code>javac</code>&#x7F16;&#x8BD1;&#x5668;&#x6B63;&#x5728;&#x7B49;&#x5F85;&#x8C03;&#x8BD5;&#x7A0B;&#x5E8F;&#x63A5;&#x5165;&#x3002;</p><p>&#x5728;<code>main/Main.java</code>&#x7C7B;&#x5185;<code>compile()</code>&#x65B9;&#x6CD5;&#x6253;&#x4E0A;&#x65AD;&#x70B9;&#xFF0C;&#x5E76;&#x542F;&#x52A8;&#x8FDC;&#x7A0B;&#x8C03;&#x8BD5;&#x7A0B;&#x5E8F;&#xFF0C;&#x5373;&#x53EF;&#x8FDB;&#x884C;<code>javac</code>&#x7684;&#x8C03;&#x8BD5;&#x3002;</p><p><img src="https://static.xuqiang.me/public/images/071324.jpg" alt="&#x8C03;&#x8BD5;"></p><p>That&#x2019;s all</p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;在做JSR269的深度解析的时候，需要对javac的源代码进行单步调试并跟踪。因此在这里记录下具体的调试步骤。&lt;/p&gt;&lt;p&gt;调试环境：&lt;br&gt;OS: MacOS 10.14.5&lt;br&gt;JDK：JDK_1.8&lt;br&gt;IDEA: IntelliJ IDEA 2019.1.3&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="Javac" scheme="https://xuqiang.me/categories/Java/Javac/"/>
    
      <category term="IDEA" scheme="https://xuqiang.me/categories/Java/Javac/IDEA/"/>
    
    
      <category term="Java" scheme="https://xuqiang.me/tags/Java/"/>
    
      <category term="Javac" scheme="https://xuqiang.me/tags/Javac/"/>
    
      <category term="Debug" scheme="https://xuqiang.me/tags/Debug/"/>
    
      <category term="IDEA" scheme="https://xuqiang.me/tags/IDEA/"/>
    
  </entry>
  
  <entry>
    <title>以DDD构造通用Shell控制台</title>
    <link href="https://xuqiang.me/DDD-console-example.html"/>
    <id>https://xuqiang.me/DDD-console-example.html</id>
    <published>2019-06-26T15:14:41.000Z</published>
    <updated>2019-06-26T16:45:57.855Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x6700;&#x8FD1;&#x4E00;&#x76F4;&#x5728;&#x4E86;&#x89E3;DDD&#x76F8;&#x5173;&#x7684;&#x77E5;&#x8BC6;&#xFF0C;&#x81EA;&#x5DF1;&#x4E5F;&#x4EE5;DDD&#x6784;&#x5EFA;&#x4E86;&#x51E0;&#x4E2A;&#x5E94;&#x7528;&#xFF1B;&#x7F51;&#x4E0A;&#x6709;&#x8BB8;&#x591A;&#x5173;&#x4E8E;DDD&#x7684;&#x7406;&#x8BBA;&#x77E5;&#x8BC6;&#xFF0C;&#x4F46;&#x662F;&#x5BF9;&#x4E8E;&#x5B9E;&#x4F8B;&#x8BB2;&#x89E3;&#xFF0C;&#x7279;&#x522B;&#x662F;Java&#x8BED;&#x8A00;&#x7684;&#x8F83;&#x4E3A;&#x7A00;&#x5C11;&#x3002;</p><a id="more"></a><h3 id="DDD&#x8BBE;&#x8BA1;&#x601D;&#x8DEF;"><a href="#DDD&#x8BBE;&#x8BA1;&#x601D;&#x8DEF;" class="headerlink" title="DDD&#x8BBE;&#x8BA1;&#x601D;&#x8DEF;"></a>DDD&#x8BBE;&#x8BA1;&#x601D;&#x8DEF;</h3><p>&#x5728;&#x8BBE;&#x8BA1;&#x63A7;&#x5236;&#x53F0;&#x8FD9;&#x4E2A;&#x5E94;&#x7528;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x6574;&#x4F53;&#x601D;&#x8DEF;&#x6CBF;&#x7528;&#x7684;&#x662F;DDD&#x9A71;&#x52A8;&#x8BBE;&#x8BA1;&#x90A3;&#x672C;&#x4E66;&#x7684;&#x601D;&#x8DEF;&#x3002;</p><ol start="0"><li>&#x6574;&#x7406;&#x7528;&#x6237;&#x7528;&#x4F8B;&#x9700;&#x6C42;</li><li>&#x6784;&#x5EFA;&#x7EDF;&#x4E00;&#x8BED;&#x8A00;</li><li>&#x6784;&#x5EFA;&#x9650;&#x754C;&#x4E0A;&#x4E0B;&#x6587;</li><li>&#x6784;&#x5EFA;&#x4E0A;&#x4E0B;&#x6587;&#x6620;&#x5C04;&#x56FE;</li><li>&#x6784;&#x5EFA;&#x9886;&#x57DF;&#x6A21;&#x578B;</li></ol><h3 id="&#x9700;&#x6C42;&#x7528;&#x4F8B;"><a href="#&#x9700;&#x6C42;&#x7528;&#x4F8B;" class="headerlink" title="&#x9700;&#x6C42;&#x7528;&#x4F8B;"></a>&#x9700;&#x6C42;&#x7528;&#x4F8B;</h3><ul><li>&#x7528;&#x6237;&#x8F93;&#x5165;&#x547D;&#x4EE4;&#xFF0C;&#x63A7;&#x5236;&#x53F0;&#x6839;&#x636E;&#x547D;&#x4EE4;&#x9009;&#x62E9;&#x6267;&#x884C;&#x8005;&#xFF0C;&#x6267;&#x884C;&#x8005;&#x6267;&#x884C;&#x547D;&#x4EE4;&#x540E;&#xFF0C;&#x54CD;&#x5E94;&#x547D;&#x4EE4;&#x8F93;&#x51FA;&#xFF0C;&#x5E76;&#x521B;&#x5EFA;&#x5FEB;&#x7167;</li><li>&#x7528;&#x6237;&#x53EF;&#x4EE5;&#x5728;&#x5F53;&#x524D;&#x4F1A;&#x8BDD;&#x67E5;&#x770B;&#x547D;&#x4EE4;&#x5FEB;&#x7167;&#xFF0C;&#x5E76;&#x4E14;&#x9009;&#x62E9;&#x64A4;&#x9500;&#x5230;&#x67D0;&#x4E2A;&#x547D;&#x4EE4;&#x5FEB;&#x7167;&#x4E0A;&#xFF0C;&#x5728;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#x524D;&#x7684;&#x6240;&#x6709;&#x547D;&#x4EE4;&#x5168;&#x90E8;&#x56DE;&#x6EDA;</li><li>&#x7528;&#x6237;&#x53EF;&#x4EE5;&#x5C06;&#x591A;&#x4E2A;&#x547D;&#x4EE4;&#x5B58;&#x50A8;&#x4E3A;&#x6279;&#x5904;&#x7406;&#x547D;&#x4EE4;&#xFF0C;&#x5728;&#x672C;&#x6B21;&#x4F1A;&#x8BDD;&#x4E2D;&#x91CD;&#x590D;&#x6027;&#x8C03;&#x7528;&#x6267;&#x884C;</li><li>&#x7528;&#x6237;&#x53EF;&#x4EE5;&#x62E6;&#x622A;&#x547D;&#x4EE4;&#x6267;&#x884C;&#x4E4B;&#x524D;&#xFF0C;&#x6267;&#x884C;&#x4EFB;&#x52A1;&#x4E4B;&#x540E;&#xFF0C;&#x6267;&#x884C;&#x4EFB;&#x52A1;&#x5931;&#x8D25;&#xFF0C;&#x6267;&#x884C;&#x4EFB;&#x52A1;&#x6210;&#x529F;&#xFF0C;&#x6267;&#x884C;&#x5B8C;&#x6210;&#x7684;&#x70B9;&#xFF1B;&#x5373;&#xFF0C;&#x547D;&#x4EE4;&#x7684;&#x751F;&#x547D;&#x5468;&#x671F;</li></ul><h4 id="&#x63D0;&#x53D6;&#x5B9E;&#x4F53;&#x6784;&#x5EFA;&#x7EDF;&#x4E00;&#x8BED;&#x8A00;"><a href="#&#x63D0;&#x53D6;&#x5B9E;&#x4F53;&#x6784;&#x5EFA;&#x7EDF;&#x4E00;&#x8BED;&#x8A00;" class="headerlink" title="&#x63D0;&#x53D6;&#x5B9E;&#x4F53;&#x6784;&#x5EFA;&#x7EDF;&#x4E00;&#x8BED;&#x8A00;"></a>&#x63D0;&#x53D6;&#x5B9E;&#x4F53;&#x6784;&#x5EFA;&#x7EDF;&#x4E00;&#x8BED;&#x8A00;</h4><p>&#x6839;&#x636E;&#x4E0A;&#x8FF0;&#x9700;&#x6C42;&#xFF0C;&#x63D0;&#x53D6;&#x540D;&#x8BCD;&#xFF0C;&#x8FD9;&#x4E9B;&#x540D;&#x8BCD;&#x5C31;&#x662F;&#x9700;&#x8981;&#x6784;&#x5EFA;&#x7684;&#x5B9E;&#x4F53;&#x3002;<br>&#x4E0A;&#x8FF0;&#x9700;&#x6C42;&#x7684;&#x5B9E;&#x4F53;&#x5305;&#x542B;&#x6709;&#xFF1A;&#x547D;&#x4EE4;&#x3001;&#x6267;&#x884C;&#x8005;&#x3001;&#x6279;&#x5904;&#x7406;&#x3001;&#x547D;&#x4EE4;&#x7ED3;&#x679C;&#x3001;&#x5386;&#x53F2;&#x3001;&#x547D;&#x4EE4;&#x5FEB;&#x7167;&#x3001;&#x56DE;&#x6EDA;&#x811A;&#x672C;&#x3001;&#x4F1A;&#x8BDD;</p><p>&#x6784;&#x5EFA;&#x51FA;&#x5982;&#x4E0B;&#x901A;&#x7528;&#x8BED;&#x8A00;&#xFF1A;</p><table><thead><tr><th>&#x540D;&#x8BCD;</th><th>&#x63CF;&#x8FF0;</th></tr></thead><tbody><tr><td>&#x547D;&#x4EE4;</td><td>&#x7528;&#x6237;&#x53D1;&#x51FA;&#x7684;&#x8BF7;&#x6C42;</td></tr><tr><td>&#x6267;&#x884C;&#x8005;</td><td>&#x8BF7;&#x6C42;&#x4EA4;&#x7531;&#x8BA1;&#x7B97;&#x673A;&#x7CFB;&#x7EDF;&#x540E;&#xFF0C;&#x4F1A;&#x4EA4;&#x7531;&#x5177;&#x4F53;&#x67D0;&#x4E2A;&#x7C7B;&#xFF0C;&#x901A;&#x8FC7;&#x8FD9;&#x4E2A;&#x7C7B;&#x5185;&#x90E8;&#x7684;&#x4E1A;&#x52A1;&#x903B;&#x8F91;&#x6267;&#x884C;&#x7528;&#x6237;&#x8BF7;&#x6C42;</td></tr><tr><td>&#x6279;&#x5904;&#x7406;</td><td>&#x7531;&#x4E00;&#x6279;&#x6B21;&#x6709;&#x5E8F;&#x7684;&#x547D;&#x4EE4;&#x7EC4;&#x6210;&#x7684;&#x4E00;&#x4E2A;&#x547D;&#x4EE4;&#x96C6;&#x5408;</td></tr><tr><td>&#x547D;&#x4EE4;&#x7ED3;&#x679C;</td><td>&#x547D;&#x4EE4;&#x6267;&#x884C;&#x5B8C;&#x6210;&#x540E;&#xFF0C;&#x8FD4;&#x56DE;&#x7ED9;&#x7528;&#x6237;&#x7684;&#x4E00;&#x4E9B;&#x7ED3;&#x679C;&#x4FE1;&#x606F;</td></tr><tr><td>&#x4F1A;&#x8BDD;</td><td>&#x7528;&#x6237;&#x5728;&#x94FE;&#x63A5;&#x63A7;&#x5236;&#x53F0;&#x540E;&#x5230;&#x65AD;&#x5F00;&#x94FE;&#x63A5;&#x7684;&#x4E00;&#x6574;&#x4E2A;&#x65F6;&#x95F4;&#x5468;&#x671F;</td></tr><tr><td>&#x5386;&#x53F2;</td><td>&#x5728;&#x5F53;&#x524D;&#x4F1A;&#x8BDD;&#x4E2D;&#xFF0C;&#x7528;&#x6237;&#x81EA;&#x521B;&#x5EFA;&#x4F1A;&#x8BDD;&#x4EE5;&#x540E;&#xFF0C;&#x6267;&#x884C;&#x7684;&#x6240;&#x6709;&#x547D;&#x4EE4;&#x5217;&#x8868;</td></tr><tr><td>&#x547D;&#x4EE4;&#x5FEB;&#x7167;</td><td>&#x5728;&#x6BCF;&#x6B21;&#x547D;&#x4EE4;&#x6267;&#x884C;&#x5B8C;&#x6210;&#x540E;&#xFF0C;&#x4F1A;&#x4FDD;&#x6301;&#x5F53;&#x6B21;&#x547D;&#x4EE4;&#x7684;&#x4FE1;&#x606F;</td></tr><tr><td>&#x56DE;&#x6EDA;&#x811A;&#x672C;</td><td>&#x5386;&#x53F2;&#x4E2D;&#x7684;&#x6BCF;&#x6B21;&#x547D;&#x4EE4;&#x5FEB;&#x7167;&#xFF0C;&#x5982;&#x679C;&#x652F;&#x6301;&#x56DE;&#x6EDA;&#xFF0C;&#x5219;&#x53EF;&#x4EE5;&#x56DE;&#x6EDA;&#x547D;&#x4EE4;</td></tr></tbody></table><h4 id="&#x6784;&#x5EFA;&#x9650;&#x754C;&#x4E0A;&#x4E0B;&#x6587;"><a href="#&#x6784;&#x5EFA;&#x9650;&#x754C;&#x4E0A;&#x4E0B;&#x6587;" class="headerlink" title="&#x6784;&#x5EFA;&#x9650;&#x754C;&#x4E0A;&#x4E0B;&#x6587;"></a>&#x6784;&#x5EFA;&#x9650;&#x754C;&#x4E0A;&#x4E0B;&#x6587;</h4><p>&#x4ECE;&#x63D0;&#x53D6;&#x7684;&#x5B9E;&#x4F53;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x6309;&#x7167;&#x201D;&#x9AD8;&#x805A;&#x5408;&#x3001;&#x4F4E;&#x8026;&#x5408;&#x201C;&#x7684;&#x65B9;&#x5F0F;&#x5212;&#x5206;&#x4E0D;&#x540C;&#x7684;&#x9886;&#x57DF;&#x805A;&#x5408;&#x3002;&#x5212;&#x5206;&#x9650;&#x754C;&#x4E0A;&#x4E0B;&#x6587;&#x5982;&#x4E0B;&#x56FE;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/%E6%88%98%E7%95%A5%E8%AE%BE%E8%AE%A1%E2%80%94%E2%80%94%E9%99%90%E7%95%8C%E4%B8%8A%E4%B8%8B%E6%96%87-1.png" alt="&#x9650;&#x754C;&#x4E0A;&#x4E0B;&#x6587;"></p><p>&#x5F88;&#x663E;&#x7136;&#xFF0C;&#x805A;&#x5408;&#x6839;&#x5DF2;&#x7ECF;&#x6E05;&#x6670;&#xFF1A;</p><ul><li>&#x547D;&#x4EE4;</li><li>&#x5386;&#x53F2;</li><li>&#x4F1A;&#x8BDD;</li></ul><h4 id="&#x6784;&#x5EFA;&#x4E0A;&#x4E0B;&#x6587;&#x6620;&#x5C04;"><a href="#&#x6784;&#x5EFA;&#x4E0A;&#x4E0B;&#x6587;&#x6620;&#x5C04;" class="headerlink" title="&#x6784;&#x5EFA;&#x4E0A;&#x4E0B;&#x6587;&#x6620;&#x5C04;"></a>&#x6784;&#x5EFA;&#x4E0A;&#x4E0B;&#x6587;&#x6620;&#x5C04;</h4><p>&#x7531;&#x9700;&#x6C42;&#x7528;&#x4F8B;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x4E86;&#x89E3;&#x5230;&#x805A;&#x5408;&#x548C;&#x805A;&#x5408;&#x4E4B;&#x95F4;&#x7684;&#x8054;&#x7CFB;&#x3002;</p><ul><li>&#x547D;&#x4EE4;&#x6267;&#x884C;&#x540E;&#x521B;&#x5EFA;</li><li>&#x5728;&#x4F1A;&#x8BDD;&#x4E2D;&#x67E5;&#x770B;&#x5386;&#x53F2;</li><li>&#x547D;&#x4EE4;&#x6267;&#x884C;&#x540E;&#x521B;&#x5EFA;&#x5FEB;&#x7167;</li></ul><p>&#x6784;&#x5EFA;&#x51FA;&#x5982;&#x4E0B;&#x4E0A;&#x4E0B;&#x6587;&#x6620;&#x5C04;&#x56FE;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/%E6%88%98%E7%95%A5%E8%AE%BE%E8%AE%A1%E2%80%94%E2%80%94%E4%B8%8A%E4%B8%8B%E6%96%87%E6%98%A0%E5%B0%84%E5%9B%BE-1.png" alt="&#x4E0A;&#x4E0B;&#x6587;&#x6620;&#x5C04;&#x56FE;"></p><h4 id="&#x6784;&#x5EFA;&#x9886;&#x57DF;&#x6A21;&#x578B;"><a href="#&#x6784;&#x5EFA;&#x9886;&#x57DF;&#x6A21;&#x578B;" class="headerlink" title="&#x6784;&#x5EFA;&#x9886;&#x57DF;&#x6A21;&#x578B;"></a>&#x6784;&#x5EFA;&#x9886;&#x57DF;&#x6A21;&#x578B;</h4><p>&#x4E0A;&#x8FF0;&#x5B9E;&#x4F53;&#x3001;&#x805A;&#x5408;&#x6839;&#x5DF2;&#x7ECF;&#x660E;&#x786E;&#xFF0C;&#x4E92;&#x76F8;&#x4E4B;&#x95F4;&#x7684;&#x5173;&#x7CFB;&#x53EF;&#x4EE5;&#x901A;&#x8FC7;&#x7528;&#x4F8B;&#x9700;&#x6C42;&#x6765;&#x63CF;&#x8FF0;&#x6E05;&#x695A;&#xFF0C;&#x6784;&#x5EFA;&#x51FA;&#x5982;&#x4E0B;&#x9886;&#x57DF;&#x6A21;&#x578B;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/Shell%E6%8E%A7%E5%88%B6%E5%8F%B0DDD%E8%AE%BE%E8%AE%A1-3.png" alt="&#x9886;&#x57DF;&#x6A21;&#x578B;"></p><h3 id="&#x65B9;&#x6848;&#x843D;&#x5730;"><a href="#&#x65B9;&#x6848;&#x843D;&#x5730;" class="headerlink" title="&#x65B9;&#x6848;&#x843D;&#x5730;"></a>&#x65B9;&#x6848;&#x843D;&#x5730;</h3><p>&#x6574;&#x4F53;&#x601D;&#x8DEF;&#x5DF2;&#x7ECF;&#x660E;&#x786E;&#xFF0C;&#x53EF;&#x4EE5;&#x6839;&#x636E;&#x4E0A;&#x8FF0;&#x7684;&#x9886;&#x57DF;&#x6A21;&#x578B;&#x6784;&#x5EFA;&#x51FA;&#x5927;&#x4F53;&#x7684;&#x9886;&#x57DF;&#x5C42;&#xFF0C;&#x4E3B;&#x8981;&#x5206;&#x4E3A;&#x4E09;&#x4E2A;&#x5305;&#xFF0C;&#x7C7B;&#x4F3C;&#x4E09;&#x4E2A;&#x9650;&#x754C;&#x4E0A;&#x4E0B;&#x6587;&#xFF1A;</p><ul><li>command</li><li>session</li><li>history</li></ul><h4 id="Command&#x6838;&#x5FC3;&#x5B50;&#x57DF;"><a href="#Command&#x6838;&#x5FC3;&#x5B50;&#x57DF;" class="headerlink" title="Command&#x6838;&#x5FC3;&#x5B50;&#x57DF;"></a>Command&#x6838;&#x5FC3;&#x5B50;&#x57DF;</h4><p>Command&#x662F;&#x6838;&#x5FC3;&#x5B50;&#x57DF;&#xFF0C;&#x662F;&#x6574;&#x4E2A;&#x63A7;&#x5236;&#x53F0;&#x7684;&#x80FD;&#x529B;&#x4F53;&#x73B0;&#xFF0C;&#x4E3B;&#x8981;&#x89E3;&#x51B3;&#x7528;&#x6237;&#x547D;&#x4EE4;&#x6267;&#x884C;&#x7684;&#x903B;&#x8F91;&#x3002;</p><p>&#x5728;&#x8FD9;&#x4E2A;&#x9650;&#x754C;&#x4E0A;&#x4E0B;&#x6587;&#x5185;&#x5B9A;&#x4E49;&#x4E86;Command&#x7C7B;&#xFF0C;&#x5E76;&#x5B9E;&#x73B0;&#x4E86;&#x6267;&#x884C;&#x3001;&#x56DE;&#x64A4;&#x7684;&#x80FD;&#x529B;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Command aggregate root</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * behavior:</span></span><br><span class="line"><span class="comment"> * 1. execute</span></span><br><span class="line"><span class="comment"> * 2. undo</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> WhatAKitty</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2019/05/01</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span></span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@EqualsAndHashCode</span>(callSuper = <span class="keyword">true</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Command</span> <span class="keyword">extends</span> <span class="title">AbstractAggregateRoot</span>&lt;<span class="title">String</span>&gt; <span class="keyword">implements</span> <span class="title">ICommand</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * command name</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> String name;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * the receiver to actually execute</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> IReceiver receiver;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Command</span><span class="params">(AggregateId&lt;String&gt; id, String name, IReceiver receiver)</span> </span>{</span><br><span class="line">        <span class="keyword">super</span>(id);</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">        <span class="keyword">this</span>.receiver = receiver;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> CommandResult <span class="title">execute</span><span class="params">(Session session)</span> </span>{</span><br><span class="line">        publishEvent(<span class="keyword">new</span> CommandBeforeExecuteEvent(session));</span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            <span class="comment">// invoke</span></span><br><span class="line">            <span class="keyword">final</span> Object result = execute(session, receiver);</span><br><span class="line">            publishEvent(<span class="keyword">new</span> CommandAfterExecuteEvent(session, result));</span><br><span class="line">            <span class="keyword">return</span> CommandResult.of(<span class="keyword">true</span>, result);</span><br><span class="line">        } <span class="keyword">catch</span> (Throwable e) {</span><br><span class="line">            publishEvent(<span class="keyword">new</span> CommandExecuteFailedEvent(session, e));</span><br><span class="line">            <span class="keyword">return</span> CommandResult.of(<span class="keyword">false</span>, <span class="keyword">null</span>);</span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            publishEvent(<span class="keyword">new</span> CommandFinishedEvent(session));</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">undo</span><span class="params">(Session session)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (!supportUndo()) {</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> UnsupportedOperationException(<span class="string">&quot;unsupported undo operation&quot;</span>);</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// undo</span></span><br><span class="line">        undo(session, receiver);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * create a batch command task</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> commands commands list</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> batch command instance</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> BatchCommand <span class="title">createBatch</span><span class="params">(List&lt;ICommand&gt; commands)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> BatchCommand(commands);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">abstract</span> Object <span class="title">execute</span><span class="params">(Session session, IReceiver receiver)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> Object <span class="title">undo</span><span class="params">(Session session, IReceiver receiver)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728;&#x8FD9;&#x91CC;&#xFF0C;Command&#x7C7B;&#x88AB;&#x58F0;&#x660E;&#x4E3A;&#x62BD;&#x8C61;&#x7C7B;&#xFF0C;&#x56E0;&#x4E3A;&#x547D;&#x4EE4;&#x8FD9;&#x4E2A;&#x805A;&#x5408;&#x6839;&#x6BD4;&#x8F83;&#x7279;&#x6B8A;&#xFF0C;&#x6BCF;&#x4E2A;&#x805A;&#x5408;&#x6839;&#x503C;&#x90FD;&#x662F;&#x4EE5;&#x7C7B;&#x7684;&#x5F62;&#x5F0F;&#x5B58;&#x5728;&#x7684;&#xFF0C;&#x6BCF;&#x4E2A;&#x5177;&#x4F53;&#x547D;&#x4EE4;&#x90FD;&#x6709;&#x81EA;&#x8EAB;&#x7684;&#x6267;&#x884C;&#x903B;&#x8F91;&#x3002;</p><p>Command&#x7C7B;&#x5185;&#x6BCF;&#x4E2A;&#x5177;&#x4F53;&#x7684;Command&#x90FD;&#x6709;&#x4E00;&#x4E2A;&#x5BF9;&#x5E94;&#x7684;Receiver&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x6267;&#x884C;&#x8005;&#xFF1B;&#x5728;&#x6267;&#x884C;&#x8005;&#x5185;&#x4F1A;&#x6267;&#x884C;&#x8FD9;&#x4E2A;&#x547D;&#x4EE4;&#x7684;&#x5177;&#x4F53;&#x903B;&#x8F91;&#xFF0C;&#x7136;&#x540E;&#x5C06;CommandResult&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x6267;&#x884C;&#x7ED3;&#x679C;&#x8FD4;&#x56DE;&#x7ED9;&#x7528;&#x6237;&#x3002;</p><p>&#x6BD4;&#x5982;&#xFF0C;&#x5728;&#x8FD9;&#x91CC;&#x9ED8;&#x8BA4;&#x5B9E;&#x73B0;&#x7684;&#x663E;&#x793A;&#x5386;&#x53F2;&#x547D;&#x4EE4;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * show history command</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> WhatAKitty</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2019/05/02</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span></span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ShowHistoryCommand</span> <span class="keyword">extends</span> <span class="title">Command</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String COMMAND_TIP = <span class="string">&quot;history&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">ShowHistoryCommand</span><span class="params">(AggregateId&lt;String&gt; id)</span> </span>{</span><br><span class="line">        <span class="keyword">super</span>(id, COMMAND_TIP, <span class="keyword">new</span> ShowHistoryReceiver());</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> Object <span class="title">execute</span><span class="params">(Session session, IReceiver receiver)</span> </span>{</span><br><span class="line">        receiver.invoke(session);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">supportUndo</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * show history receiver</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">ShowHistoryReceiver</span> <span class="keyword">extends</span> <span class="title">Receiver</span> </span>{</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">ShowHistoryReceiver</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">super</span>(session -&gt; session.getHistory().showHistory());</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5386;&#x53F2;&#x547D;&#x4EE4;&#x7EE7;&#x627F;&#x4E86;Command&#x62BD;&#x8C61;&#x7C7B;&#xFF0C;&#x5B83;&#x662F;&#x4E00;&#x4E2A;&#x5177;&#x4F53;&#x7684;&#x805A;&#x5408;&#x6839;&#x503C;&#x3002;&#x5728;&#x547D;&#x4EE4;&#x6267;&#x884C;&#x903B;&#x8F91;&#x8FD9;&#x91CC;&#xFF0C;&#x5B83;&#x5C06;&#x4F1A;&#x8BDD;&#x53C2;&#x6570;&#x4F20;&#x9012;&#x5230;&#x4E86;&#x6267;&#x884C;&#x8005;&#x5904;&#xFF0C;&#x8FDB;&#x884C;&#x5177;&#x4F53;&#x7684;&#x6267;&#x884C;&#x3002;<br>&#x5728;&#x8FD9;&#x6BB5;&#x903B;&#x8F91;&#x5185;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">super</span>(session -&gt; session.getHistory().showHistory());</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x4F1A;&#x8BDD;&#x672C;&#x8EAB;&#x4F1A;&#x83B7;&#x53D6;&#x4F1A;&#x8BDD;&#x5185;&#x5B58;&#x50A8;&#x7684;&#x547D;&#x4EE4;&#x5386;&#x53F2;&#xFF0C;&#x5E76;&#x6267;&#x884C;&#x5B83;&#x7684;&#x80FD;&#x529B;&#xFF0C;&#x663E;&#x793A;&#x5386;&#x53F2;&#x547D;&#x4EE4;&#x5FEB;&#x7167;&#x5217;&#x8868;&#x3002;</p><h4 id="Session&#x652F;&#x6491;&#x5B50;&#x57DF;"><a href="#Session&#x652F;&#x6491;&#x5B50;&#x57DF;" class="headerlink" title="Session&#x652F;&#x6491;&#x5B50;&#x57DF;"></a>Session&#x652F;&#x6491;&#x5B50;&#x57DF;</h4><p>Session&#x4F5C;&#x4E3A;&#x627F;&#x4E0A;&#x542F;&#x4E0B;&#x7684;&#x652F;&#x6491;&#x5B50;&#x57DF;&#xFF0C;&#x5185;&#x90E8;&#x80FD;&#x529B;&#x975E;&#x5E38;&#x4E30;&#x5BCC;&#xFF0C;&#x5305;&#x542B;&#x6709;&#x6DFB;&#x52A0;&#x7528;&#x6237;&#x81EA;&#x5B9A;&#x4E49;&#x53C2;&#x6570;&#x3001;&#x83B7;&#x53D6;&#x53C2;&#x6570;&#x3001;&#x7ED1;&#x5B9A;&#x547D;&#x4EE4;&#x5FEB;&#x7167;&#x5386;&#x53F2;&#x3001;&#x8BBE;&#x7F6E;&#x5F53;&#x524D;&#x6267;&#x884C;&#x547D;&#x4EE4;&#x7B49;&#x7B49;&#x80FD;&#x529B;&#x3002;</p><p>&#x5728;&#x8FD9;&#x91CC;&#x4E3B;&#x8981;&#x63CF;&#x8FF0;&#x5B83;&#x7684;&#x7ED1;&#x5B9A;&#x5386;&#x53F2;&#x4EE5;&#x53CA;&#x8BBE;&#x7F6E;&#x5F53;&#x524D;&#x547D;&#x4EE4;&#x7684;&#x4E24;&#x4E2A;&#x80FD;&#x529B;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * bind history into this session</span></span><br><span class="line"><span class="comment">  *</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@param</span> fetcher not exists history, do get it from fetcher</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> History <span class="title">bindHistory</span><span class="params">(HistoryFetcher fetcher)</span> </span>{</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">this</span>.history != <span class="keyword">null</span>) {</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.history;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">synchronized</span> (HISTORY_LOCK) {</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span>.history == <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">this</span>.history = fetcher.invoke();</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.history;</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5982;&#x4E0A;&#x4EE3;&#x7801;&#x662F;&#x7ED1;&#x5B9A;&#x5386;&#x53F2;&#x7684;&#x5177;&#x4F53;&#x5B9E;&#x73B0;&#xFF0C;&#x5982;&#x679C;&#x5728;&#x53D1;&#x73B0;&#x5F53;&#x524D;&#x4F1A;&#x8BDD;&#x65E0;&#x5386;&#x53F2;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#xFF0C;&#x4F1A;&#x5728;&#x52A0;&#x9501;&#x7684;&#x6761;&#x4EF6;&#x4E0B;&#xFF0C;&#x4ECE;<code>fetcher</code>&#x4E2D;&#x83B7;&#x53D6;&#x547D;&#x4EE4;&#x5386;&#x53F2;&#x7684;&#x5B9E;&#x4F8B;&#x8FDB;&#x884C;&#x7ED1;&#x5B9A;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * current command to execute</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="meta">@Getter</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> ThreadLocal&lt;ICommand&gt; command = <span class="keyword">new</span> ThreadLocal&lt;&gt;();</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setCurrentCommand</span><span class="params">(ICommand cmd)</span> </span>{</span><br><span class="line">    command.set(cmd);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> ICommand <span class="title">currentCommand</span><span class="params">()</span> </span>{</span><br><span class="line">    <span class="keyword">return</span> command.get();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">removeCommand</span><span class="params">()</span> </span>{</span><br><span class="line">    command.remove();</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x8BBE;&#x7F6E;&#x5F53;&#x524D;&#x547D;&#x4EE4;&#x3001;&#x83B7;&#x53D6;&#x5F53;&#x524D;&#x547D;&#x4EE4;&#x3001;&#x79FB;&#x9664;&#x5F53;&#x524D;&#x547D;&#x4EE4;&#x4E3B;&#x8981;&#x901A;&#x8FC7;<code>ThreadLocal</code>&#x7C7B;&#x6765;&#x5B9E;&#x73B0;&#xFF0C;&#x6309;&#x7167;&#x63A7;&#x5236;&#x53F0;&#x8BBE;&#x8BA1;&#xFF0C;&#x7528;&#x6237;&#x5728;&#x6267;&#x884C;&#x67D0;&#x4E2A;&#x547D;&#x4EE4;&#x7684;&#x65F6;&#x5019;&#x662F;&#x5355;&#x7EBF;&#x7A0B;&#x64CD;&#x4F5C;&#x3002;</p><h4 id="&#x5386;&#x53F2;&#x5B50;&#x57DF;"><a href="#&#x5386;&#x53F2;&#x5B50;&#x57DF;" class="headerlink" title="&#x5386;&#x53F2;&#x5B50;&#x57DF;"></a>&#x5386;&#x53F2;&#x5B50;&#x57DF;</h4><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * history aggregate root</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> WhatAKitty</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2019/05/02</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span></span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">History</span> <span class="keyword">extends</span> <span class="title">AbstractAggregateRoot</span>&lt;<span class="title">String</span>&gt; </span>{</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * the stack of command snapshot</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Stack&lt;CommandSnapshot&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * session</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Session session;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">History</span><span class="params">(AggregateId&lt;String&gt; id, Session session)</span> </span>{</span><br><span class="line">        <span class="keyword">super</span>(id);</span><br><span class="line">        <span class="keyword">this</span>.session = session;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * add command into history stack</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> command the command to execute successfully</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addHistory</span><span class="params">(ICommand command)</span> </span>{</span><br><span class="line">        <span class="comment">// ignore history command itself</span></span><br><span class="line">        <span class="keyword">if</span> (command <span class="keyword">instanceof</span> ShowHistoryCommand) {</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// create command snapshot and push the snapshot into history stack</span></span><br><span class="line">        stack.push(CommandSnapshot.snapshot(command));</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * show the commands execute previously</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">showHistory</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">int</span> total = stack.size();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; total; i++) {</span><br><span class="line">            CommandSnapshot snapshot = stack.get(i);</span><br><span class="line">            StreamMgr.getINSTANCE().println(String.format(<span class="string">&quot;[%s] %s&quot;</span>, i + <span class="number">1</span>, snapshot.getName()));</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * rollback the current stage</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> index the rollback index, started with 1</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">rollback</span><span class="params">(<span class="keyword">int</span> index)</span> </span>{</span><br><span class="line">        <span class="comment">// check arguments</span></span><br><span class="line">        <span class="keyword">if</span> (index &lt; <span class="number">1</span> || stack.size() &lt; index) {</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">&quot;exceed max rollback&quot;</span>);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= index; i++) {</span><br><span class="line">            CommandSnapshot snapshot = stack.remove(i - <span class="number">1</span>);</span><br><span class="line">            snapshot.undo(session);</span><br><span class="line">            StreamMgr.getINSTANCE().println(String.format(<span class="string">&quot;The command %s has been undo&quot;</span>, snapshot.getName()));</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5386;&#x53F2;&#x5B50;&#x57DF;&#x662F;&#x5BF9;&#x547D;&#x4EE4;&#x5FEB;&#x7167;&#x7684;&#x4E00;&#x4E2A;&#x7BA1;&#x7406;&#xFF0C;&#x5728;&#x6267;&#x884C;&#x5B8C;&#x547D;&#x4EE4;&#x540E;&#xFF0C;&#x53EF;&#x4EE5;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x547D;&#x4EE4;&#x5FEB;&#x7167;&#x5B58;&#x5165;&#x5386;&#x53F2;&#x6808;&#x5185;&#xFF1B;&#x5728;&#x5C55;&#x73B0;&#x547D;&#x4EE4;&#x5FEB;&#x7167;&#x5217;&#x8868;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x53EF;&#x4EE5;&#x4ECE;&#x7AD9;&#x5185;&#x8BFB;&#x53D6;&#x547D;&#x4EE4;&#x5FEB;&#x7167;&#x3002;&#x5728;&#x56DE;&#x6EDA;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x53EF;&#x4EE5;&#x4EE5;&#x6808;&#x7684;&#x5F62;&#x5F0F;&#x51FA;&#x6808;&#x5E76;&#x6267;&#x884C;&#x56DE;&#x6EDA;&#x547D;&#x4EE4;&#xFF0C;&#x5982;&#x679C;&#x547D;&#x4EE4;&#x4E0D;&#x652F;&#x6301;&#x56DE;&#x6EDA;&#xFF0C;&#x5219;&#x4F1A;&#x56DE;&#x6EDA;&#x5931;&#x8D25;&#x3002;</p><h4 id="Application&#x5C42;&#x4EE5;&#x53CA;&#x4ED3;&#x50A8;&#x5C42;"><a href="#Application&#x5C42;&#x4EE5;&#x53CA;&#x4ED3;&#x50A8;&#x5C42;" class="headerlink" title="Application&#x5C42;&#x4EE5;&#x53CA;&#x4ED3;&#x50A8;&#x5C42;"></a>Application&#x5C42;&#x4EE5;&#x53CA;&#x4ED3;&#x50A8;&#x5C42;</h4><p>&#x5E94;&#x7528;&#x63A7;&#x5236;&#x53F0;&#x4E3B;&#x8981;&#x4E3A;&#x4E86;&#x80FD;&#x591F;&#x8BA9;&#x7528;&#x6237;&#x8C03;&#x7528;&#x547D;&#x4EE4;&#xFF0C;&#x90A3;&#x4E48;&#x52BF;&#x5FC5;&#x9700;&#x8981;&#x5C06;&#x5404;&#x9886;&#x57DF;&#x7684;&#x80FD;&#x529B;&#x505A;&#x4E00;&#x4E2A;&#x7ED3;&#x5408;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * command service</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * execute command and add execute history</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> WhatAKitty</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2019/05/02</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span></span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@RequiredArgsConstructor</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CommandService</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> CommandRepository commandRepository;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> HistoryRepository historyRepository;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> HistoryFactory historyFactory;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x6267;&#x884C;&#x547D;&#x4EE4;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> session session</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> cmd     command</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Optional&lt;CommandResult&gt; <span class="title">execute</span><span class="params">(Session session, String cmd)</span> </span>{</span><br><span class="line">        <span class="comment">// &#x83B7;&#x53D6;&#x6216;&#x8005;&#x91CD;&#x65B0;&#x521B;&#x5EFA;&#x7ED1;&#x5B9A;&#x4E00;&#x4E2A;&#x547D;&#x4EE4;&#x5386;&#x53F2;</span></span><br><span class="line">        session.bindHistory(() -&gt; {</span><br><span class="line">          <span class="comment">// &#x521B;&#x5EFA;&#x547D;&#x4EE4;&#x5386;&#x53F2;</span></span><br><span class="line">            History newOne = historyFactory.create(session);</span><br><span class="line">            historyRepository.create(newOne);</span><br><span class="line">            <span class="keyword">return</span> newOne;</span><br><span class="line">        });</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &#x6267;&#x884C;&#x5177;&#x4F53;&#x547D;&#x4EE4;</span></span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            <span class="comment">// &#x6839;&#x636E;cmd&#x4ECE;&#x4ED3;&#x50A8;&#x4E2D;&#x83B7;&#x53D6;&#x67D0;&#x4E2A;&#x5177;&#x4F53;&#x547D;&#x4EE4;&#x6765;&#x6267;&#x884C;  &#x2460;</span></span><br><span class="line">            <span class="keyword">return</span> commandRepository.findById(AggregateId.of(cmd))</span><br><span class="line">                .map(command -&gt; {</span><br><span class="line">                    session.setCurrentCommand(command);</span><br><span class="line">                    <span class="keyword">return</span> command.execute(session);</span><br><span class="line">                });</span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            session.removeCommand();</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x521B;&#x5EFA;&#x6279;&#x5904;&#x7406;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> session   session</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> batchName batch command name</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> cmds      user defined command list</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> create successfully</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">createBatch</span><span class="params">(Session session, String batchName, List&lt;String&gt; cmds)</span> </span>{</span><br><span class="line">        <span class="comment">// &#x4ECE;&#x4ED3;&#x50A8;&#x4E2D;&#x83B7;&#x53D6;&#x6240;&#x6709;&#x547D;&#x4EE4; &#x2461;</span></span><br><span class="line">        List&lt;ICommand&gt; commands = commandRepository.findInIds(cmds.parallelStream()</span><br><span class="line">            .map(AggregateId::of)</span><br><span class="line">            .collect(Collectors.toList()));</span><br><span class="line">        BatchCommand batchCommand = Command.createBatch(commands);</span><br><span class="line">        <span class="comment">// &#x5C06;&#x6279;&#x5904;&#x7406;&#x4F5C;&#x4E3A;&#x4E00;&#x4E2A;&#x65B0;&#x547D;&#x4EE4;&#x5B58;&#x50A8;&#x5230;&#x4ED3;&#x50A8; &#x2462;</span></span><br><span class="line">        <span class="keyword">return</span> commandRepository.saveCommand(batchName, batchCommand);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728;&#x2460;&#x3001;&#x2461;&#x3001;&#x2462;&#x5904;&#xFF0C;&#x90FD;&#x9700;&#x8981;&#x8DDF;&#x4ED3;&#x50A8;&#x4EA4;&#x4E92;&#xFF0C;&#x5728;&#x4ED3;&#x50A8;&#x4E2D;&#xFF0C;&#x5B58;&#x50A8;&#x4E86;<code>cmd</code>&#x4EE5;&#x53CA;<code>command</code>&#x7684;&#x5B9E;&#x4F8B;&#xFF1B;&#x5728;&#x6BCF;&#x6B21;&#x5E94;&#x7528;&#x542F;&#x52A8;&#x540E;&#xFF0C;&#x90FD;&#x4F1A;&#x8BB2;&#x547D;&#x4EE4;&#x4EE5;&#x53CA;&#x547D;&#x4EE4;&#x5B9E;&#x4F8B;&#x7684;&#x6620;&#x5C04;&#x52A0;&#x8F7D;&#x5230;&#x5185;&#x5B58;&#x4E2D;&#x4EE5;&#x4F9B;&#x4F7F;&#x7528;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * default command repository</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> WhatAKitty</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2019/05/03</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span></span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DefaultCommandRepository</span> <span class="keyword">extends</span> <span class="title">InMemoryRepository</span>&lt;<span class="title">String</span>, <span class="title">ICommand</span>&gt; <span class="keyword">implements</span> <span class="title">CommandRepository</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Optional&lt;ICommand&gt; <span class="title">findById</span><span class="params">(AggregateId&lt;String&gt; commandId)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> Optional.ofNullable(get(commandId));</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;ICommand&gt; <span class="title">findInIds</span><span class="params">(List&lt;AggregateId&lt;String&gt;&gt; commandIds)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> commandIds.parallelStream()</span><br><span class="line">            .map(<span class="keyword">this</span>::get)</span><br><span class="line">            .filter(Objects::nonNull)</span><br><span class="line">            .collect(Collectors.toList());</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">saveCommand</span><span class="params">(String commmandName, ICommand command)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> putIfAbsent(AggregateId.of(commmandName), command) == <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="comment">// &#x6BCF;&#x6B21;&#x542F;&#x52A8;&#x540E;&#xFF0C;&#x90FD;&#x4F1A;&#x52A0;&#x8F7D;&#x5982;&#x4E0B;&#x4E24;&#x4E2A;&#x547D;&#x4EE4;&#x3002; &#x2463;</span></span><br><span class="line">        AggregateId&lt;String&gt; showHistoryId = AggregateId.of(ShowHistoryCommand.COMMAND_TIP);</span><br><span class="line">        AggregateId&lt;String&gt; undoHistoryId = AggregateId.of(UnDoCommand.COMMAND_TIP);</span><br><span class="line">        put(showHistoryId, <span class="keyword">new</span> ShowHistoryCommand(showHistoryId));</span><br><span class="line">        put(undoHistoryId, <span class="keyword">new</span> UnDoCommand(undoHistoryId));</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728;&#x2463;&#x5904;&#x52A0;&#x8F7D;&#x4E86;&#x9ED8;&#x8BA4;&#x7684;&#x4E24;&#x4E2A;&#x547D;&#x4EE4;&#xFF0C;&#x4E00;&#x4E2A;&#x662F;&#x5C55;&#x793A;&#x5386;&#x53F2;&#x3001;&#x4E00;&#x4E2A;&#x662F;&#x56DE;&#x6EDA;&#x547D;&#x4EE4;&#x3002;</p><p>&#x5982;&#x679C;&#x9700;&#x8981;&#x6269;&#x5C55;&#xFF0C;&#x5219;&#x53EF;&#x4EE5;&#x7EE7;&#x627F;&#x5E76;&#x8986;&#x5199;&#x8BE5;&#x65B9;&#x6CD5;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DemoCommandRepository</span> <span class="keyword">extends</span> <span class="title">DefaultCommandRepository</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">super</span>.init();</span><br><span class="line">        <span class="keyword">final</span> AggregateId&lt;String&gt; id = AggregateId.of(SayHelloWorldCommand.COMMAND_TIP);</span><br><span class="line">        put(id, <span class="keyword">new</span> SayHelloWorldCommand(id));</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><h3 id="&#x603B;&#x7ED3;"><a href="#&#x603B;&#x7ED3;" class="headerlink" title="&#x603B;&#x7ED3;"></a>&#x603B;&#x7ED3;</h3><p>That&#x2019;s all.</p><h3 id="&#x9644;&#x5F55;"><a href="#&#x9644;&#x5F55;" class="headerlink" title="&#x9644;&#x5F55;"></a>&#x9644;&#x5F55;</h3><p><a href="https://github.com/WhatAKitty/jmore-builder/blob/master/jmore-console" target="_blank" rel="noopener">&#x57FA;&#x7840;&#x63A7;&#x5236;&#x53F0;&#x4EE3;&#x7801;</a><br><a href="https://github.com/WhatAKitty/jmore-builder/blob/master/jmore-console-demo" target="_blank" rel="noopener">&#x63A7;&#x5236;&#x53F0;&#x6837;&#x4F8B;&#x4EE3;&#x7801;</a></p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;最近一直在了解DDD相关的知识，自己也以DDD构建了几个应用；网上有许多关于DDD的理论知识，但是对于实例讲解，特别是Java语言的较为稀少。&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="DDD" scheme="https://xuqiang.me/categories/Java/DDD/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="ddd" scheme="https://xuqiang.me/tags/ddd/"/>
    
  </entry>
  
  <entry>
    <title>一次JVM-Crash分析</title>
    <link href="https://xuqiang.me/%E4%B8%80%E6%AC%A1JVM-Crash%E5%88%86%E6%9E%90.html"/>
    <id>https://xuqiang.me/一次JVM-Crash分析.html</id>
    <published>2019-05-14T13:53:30.000Z</published>
    <updated>2019-05-14T14:08:12.451Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x4ECA;&#x65E5;&#x5728;&#x7EBF;&#x4E0A;linux&#x67E5;&#x770B;&#x65E5;&#x5FD7;&#x8FFD;&#x8E2A;&#x4E00;&#x4E2A;&#x95EE;&#x9898;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x9489;&#x9489;&#x7A81;&#x7136;&#x63A5;&#x6536;&#x5230;&#x544A;&#x8B66;&#x4FE1;&#x606F;&#xFF0C;&#x63D0;&#x793A;&#x670D;&#x52A1;crash&#x3002;</p><a id="more"></a><h3 id="&#x8FFD;&#x67E5;&#x8FC7;&#x7A0B;"><a href="#&#x8FFD;&#x67E5;&#x8FC7;&#x7A0B;" class="headerlink" title="&#x8FFD;&#x67E5;&#x8FC7;&#x7A0B;"></a>&#x8FFD;&#x67E5;&#x8FC7;&#x7A0B;</h3><p>&#x7531;&#x4E8E;&#x5728;JVM&#x542F;&#x52A8;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x5E76;&#x672A;&#x52A0;&#x5165;<code>-XX:ErrorFile</code>&#x53C2;&#x6570;&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x8BF4;&#x6CA1;&#x6709;JVM crash&#x7684;&#x65E5;&#x5FD7;&#x53EF;&#x4EE5;&#x67E5;&#x770B;&#x3002;&#x670D;&#x52A1;&#x5668;&#x91C7;&#x7528;&#x7684;&#x662F;Centos&#x7684;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#xFF0C;&#x5C31;&#x60F3;&#x5230;&#x53EF;&#x4EE5;&#x5229;&#x7528;linux&#x8FDB;&#x7A0B;&#x76D1;&#x63A7;&#x65E5;&#x5FD7;&#x67E5;&#x770B;crash&#x4FE1;&#x606F;&#x3002;</p><p>&#x8F93;&#x5165;&#x547D;&#x4EE4;<code>cat /var/log/messages</code>&#x83B7;&#x5F97;&#x5982;&#x4E0B;&#x9519;&#x8BEF;&#x8FDB;&#x7A0B;&#x751F;&#x547D;&#x5468;&#x671F;&#xFF1A;<br></p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line">May 13 13:46:19 xxxxxxxxxxxxxxxxxxxxxxx kernel: AliYunDun invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0   &#x2460;</span><br><span class="line">May 13 13:46:19 xxxxxxxxxxxxxxxxxxxxxxx kernel: AliYunDun cpuset=/ mems_allowed=0</span><br><span class="line">May 13 13:46:19 xxxxxxxxxxxxxxxxxxxxxxx kernel: CPU: 1 PID: 11084 Comm: AliYunDun Not tainted 3.x.x-x.x.x.x.x86_64 #1</span><br><span class="line">May 13 13:46:19 xxxxxxxxxxxxxxxxxxxxxxx kernel: Hardware name: Alibaba Cloud Alibaba Cloud ECS, BIOS rel-1.7.5-0-xxxxxx-20xxxxxx_164612-nilsson.home.kraxel.org xx/xx/xxxx</span><br><span class="line">...</span><br><span class="line">May 13 13:46:19 xxxxxxxxxxxxxxxxxxxxxxx kernel: Call Trace:</span><br><span class="line">May 13 13:46:19 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff816a3db1&gt;] dump_stack+0x19/0x1b</span><br><span class="line">May 13 13:46:19 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff8169f1a6&gt;] dump_header+0x90/0x229</span><br><span class="line">May 13 13:46:19 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff810e939c&gt;] ? ktime_get_ts64+0x4c/0xf0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff8113d36f&gt;] ? delayacct_end+0x8f/0xb0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff81186394&gt;] oom_kill_process+0x254/0x3d0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff81185e3d&gt;] ? oom_unkillable_task+0xcd/0x120</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff81185ee6&gt;] ? find_lock_task_mm+0x56/0xc0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff81186bd6&gt;] out_of_memory+0x4b6/0x4f0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff8169fcaa&gt;] __alloc_pages_slowpath+0x5d6/0x724</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff8118cd85&gt;] __alloc_pages_nodemask+0x405/0x420</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff811d1108&gt;] alloc_pages_current+0x98/0x110</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff81182917&gt;] __page_cache_alloc+0x97/0xb0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff81184eb0&gt;] filemap_fault+0x170/0x410</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffffc01be156&gt;] ext4_filemap_fault+0x36/0x50 [ext4]</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff811ad162&gt;] __do_fault+0x52/0xe0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff811ad60b&gt;] do_read_fault.isra.44+0x4b/0x130</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff811b1f11&gt;] handle_mm_fault+0x691/0xfa0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff816a8fad&gt;] ? __schedule+0x39d/0x8b0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff816afff4&gt;] __do_page_fault+0x154/0x450</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff816b03d6&gt;] trace_do_page_fault+0x56/0x150</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff816afa6a&gt;] do_async_page_fault+0x1a/0xd0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [&lt;ffffffff816ac578&gt;] async_page_fault+0x28/0x30</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Mem-Info:</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: active_anon:908086 inactive_anon:113 isolated_anon:0#012 active_file:1161 inactive_file:3251 isolated_file:27#012 unevictable:0 dirty:6 writeback:0 unstable:0#012 slab_reclaimable:14131 slab_unreclaimable:4393#012 mapped:372 shmem:188 pagetables:3329 bounce:0#012 free:22809 free_pcp:71 free_cma:0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Node 0 DMA free:15360kB min:276kB low:344kB high:412kB active_anon:384kB inactive_anon:0kB active_file:4kB inactive_file:4kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15992kB managed:15908kB mlocked:0kB dirty:0kB writeback:0kB mapped:4kB shmem:0kB slab_reclaimable:24kB slab_unreclaimable:32kB kernel_stack:0kB pagetables:8kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:696 all_unreclaimable? yes</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: lowmem_reserve[]: 0 2814 3773 3773</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Node 0 DMA32 free:53992kB min:50208kB low:62760kB high:75312kB active_anon:2728428kB inactive_anon:400kB active_file:4144kB inactive_file:15476kB unevictable:0kB isolated(anon):0kB isolated(file):108kB present:3129216kB managed:2884232kB mlocked:0kB dirty:24kB writeback:0kB mapped:1456kB shmem:648kB slab_reclaimable:40652kB slab_unreclaimable:9472kB kernel_stack:7824kB pagetables:10588kB unstable:0kB bounce:0kB free_pcp:360kB local_pcp:120kB free_cma:0kB writeback_tmp:0kB pages_scanned:19438 all_unreclaimable? yes</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: lowmem_reserve[]: 0 0 958 958</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Node 0 Normal free:17048kB min:17096kB low:21368kB high:25644kB active_anon:904132kB inactive_anon:52kB active_file:496kB inactive_file:624kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:1048576kB managed:981548kB mlocked:0kB dirty:0kB writeback:0kB mapped:28kB shmem:104kB slab_reclaimable:15848kB slab_unreclaimable:8068kB kernel_stack:2352kB pagetables:2720kB unstable:0kB bounce:0kB free_pcp:144kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:3131 all_unreclaimable? yes</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: lowmem_reserve[]: 0 0 0 0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Node 0 DMA: xxxx...</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Node 0 DMA32: xxxx...</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Node 0 Normal: xxxx...</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: 5490 total pagecache pages</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: 0 pages in swap cache</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Swap cache stats: add 0, delete 0, find 0/0</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Free swap  = 0kB</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Total swap = 0kB</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: 1048446 pages RAM</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: 0 pages HighMem/MovableOnly</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: 78024 pages reserved</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  335]     0   335    21498       88      42        0             0 systemd-journal</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  357]     0   357    49101       93      28        0             0 lvmetad</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  366]     0   366    11047      223      21        0         -1000 systemd-udevd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  448]     0   448     5402       70      16        0             0 irqbalance</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  450]    81   450     6104      100      18        0          -900 dbus-daemon</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  452]   997   452   133564     2422      56        0             0 polkitd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  454]     0   454     6110      137      18        0             0 systemd-logind</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  461]     0   461    31559      163      19        0             0 crond</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  462]     0   462     6464       52      18        0             0 atd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  487]     0   487    27511       32      10        0             0 agetty</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  488]     0   488    27511       33      11        0             0 agetty</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  502]    38   502    11282      188      28        0             0 ntpd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  699]     0   699    26499      255      53        0         -1000 sshd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [  700]     0   700   140609     3183      91        0             0 tuned</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [ 3171]     0  3171    29478      157      12        0             0 wrapper</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [ 3173]     0  3173   639160    17634      93        0             0 java</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [18771]     0 18771    12428      375      22        0             0 ilogtail_0.16.1</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [18772]     0 18772    35548     1153      49        0             0 ilogtail_0.16.1</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [11045]     0 11045     8187      424      21        0             0 AliYunDunUpdate</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [11063]     0 11063    34061     2169      63        0             0 AliYunDun</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [28916]     0 28916   158555      797     165        0             0 rsyslogd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [20779]   996 20779    24617      279      48        0             0 xxx_agentd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [20780]   996 20780    24642      362      48        0             0 xxx_agentd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [20781]   996 20781    24642      311      48        0             0 xxx_agentd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [20782]   996 20782    24642      323      48        0             0 xxx_agentd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [20783]   996 20783    24642      305      48        0             0 xxx_agentd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [20784]   996 20784    24617      287      48        0             0 xxx_agentd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [14212]     0 14212    37927      840      24        0             0 xxxxxx-collect</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [ 6680]     0  6680    74406     5748      60        0             0 filexxxx</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [28753]     0 28753    10448      216      13        0             0 aliyun-service</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [28775]  1000 28775  1303596   610152    1401        0             0 java</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [29015]     0 29015    36554      335      73        0             0 sshd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [29020]  1000 29020    36554      325      71        0             0 sshd</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [29021]  1000 29021    28848      113      13        0             0 bash</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: [29143]  1000 29143   288690   251514     517        0             0 vim</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Out of memory: Kill process 28775 (java) score 630 or sacrifice child      &#x2461;</span><br><span class="line">May 13 13:46:20 xxxxxxxxxxxxxxxxxxxxxxx kernel: Killed process 28775 (java) total-vm:5214384kB, anon-rss:2440608kB, file-rss:0kB, shmem-rss:0kB</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x5728;&#x2460;&#x5904;&#x53EF;&#x4EE5;&#x770B;&#x5230;AliyunDun&#x7684;&#x4E00;&#x4E2A;&#x65E5;&#x5FD7;&#xFF0C;&#x5728;&#x8FD9;&#x91CC;&#x89E6;&#x53D1;&#x4E86;&#x4E00;&#x4E2A;OOM Killer&#x3002;&#x7136;&#x540E;&#x5E72;&#x6389;&#x4E86;OOM Score&#x6700;&#x9AD8;&#x7684;Java &#x8FDB;&#x7A0B;&#x3002;</p><p>&#x800C;&#x5728;&#x2461;&#x5904;&#x53EF;&#x4EE5;&#x770B;&#x5230;OOM Killer&#x771F;&#x5B9E;&#x7684;&#x6740;&#x6B7B;&#x4E86;&#x8FDB;&#x7A0B;ID&#x4E3A;28775&#x7684;java&#x8FDB;&#x7A0B;&#x3002;</p><p>&#x60F3;&#x4E86;&#x4E0B;&#xFF0C;13::46&#x5DE6;&#x53F3;&#xFF0C;&#x521A;&#x597D;&#x6253;&#x5F00;&#x4E86;&#x4E00;&#x4E2A;2G&#x7684;&#x65E5;&#x5FD7;&#x6587;&#x4EF6;&#xFF0C;&#x5F88;&#x53EF;&#x80FD;&#x662F;&#x8FD9;&#x4E2A;&#x539F;&#x56E0;&#xFF0C;&#x9020;&#x6210;AliyunDun&#x7533;&#x8BF7;&#x5185;&#x5B58;&#x4E0D;&#x8DB3;&#xFF0C;&#x56E0;&#x6B64;&#x89E6;&#x53D1;OOM Killer&#x6740;&#x6B7B;&#x8FDB;&#x7A0B;&#x3002;</p><h3 id="&#x4EC0;&#x4E48;&#x662F;OOM-Killer"><a href="#&#x4EC0;&#x4E48;&#x662F;OOM-Killer" class="headerlink" title="&#x4EC0;&#x4E48;&#x662F;OOM Killer"></a>&#x4EC0;&#x4E48;&#x662F;OOM Killer</h3><p>OOM Killer &#x987E;&#x540D;&#x601D;&#x4E49;&#x5373;&#x4E3A;&#x5728;out of memory&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#x6740;&#x6B7B;&#x5360;&#x5185;&#x5B58;&#x6700;&#x591A;&#x53C8;&#x4E0D;&#x91CD;&#x8981;&#x7684;&#x8FDB;&#x7A0B;&#x7684;&#x7A0B;&#x5E8F;&#x3002;</p><h3 id="&#x4E3A;&#x4EC0;&#x4E48;&#x4F1A;&#x5B58;&#x5728;OOM-Killer"><a href="#&#x4E3A;&#x4EC0;&#x4E48;&#x4F1A;&#x5B58;&#x5728;OOM-Killer" class="headerlink" title="&#x4E3A;&#x4EC0;&#x4E48;&#x4F1A;&#x5B58;&#x5728;OOM Killer"></a>&#x4E3A;&#x4EC0;&#x4E48;&#x4F1A;&#x5B58;&#x5728;OOM Killer</h3><p>&#x8FD9;&#x4E2A;&#x95EE;&#x9898;&#x6E90;&#x4E8E;Linux&#x7684;&#x5185;&#x5B58;&#x7533;&#x8BF7;&#x673A;&#x5236;&#xFF0C;&#x5B83;&#x6267;&#x884C;&#x7684;&#x662F;&#x4E00;&#x4E2A;&#x79EF;&#x6781;&#x7684;&#x5185;&#x5B58;&#x7533;&#x8BF7;&#x7B56;&#x7565;&#x3002;</p><p>&#x5373;&#xFF1A;&#x6267;&#x884C;<code>maclloc()</code>&#x8FD4;&#x56DE;&#x975E;null&#x7684;&#x5730;&#x5740;&#x5E76;&#x4E0D;&#x80FD;&#x4FDD;&#x8BC1;&#x5185;&#x5B58;&#x662F;&#x771F;&#x5B9E;&#x53EF;&#x7528;&#x7684;&#xFF08;&#x5728;<code>maclloc()</code>&#x7533;&#x8BF7;&#x5185;&#x5B58;&#x7684;&#x673A;&#x5236;&#x4E2D;&#x63CF;&#x8FF0;&#x8FD9;&#x662F;&#x4E2A;&#x975E;&#x5E38;&#x5751;&#x7684;BUG&#xFF09;&#xFF0C;&#x56E0;&#x4E3A;linux&#x5141;&#x8BB8;&#x7A0B;&#x5E8F;&#x7533;&#x8BF7;&#x6BD4;&#x7CFB;&#x7EDF;&#x53EF;&#x7528;&#x7A7A;&#x95F4;&#x66F4;&#x591A;&#x7684;&#x7A7A;&#x95F4;&#xFF0C;&#x8BE5;&#x7279;&#x6027;&#x88AB;&#x79F0;&#x4E3A;<code>overcommit</code>&#x7279;&#x6027;&#xFF0C;&#x8FD9;&#x6837;&#x505A;&#x662F;&#x4E3A;&#x4E86;&#x7CFB;&#x7EDF;&#x4F18;&#x5316;&#x3002;&#x5E76;&#x4E14;&#x5E76;&#x4E0D;&#x662F;&#x6240;&#x6709;&#x7A0B;&#x5E8F;&#x7533;&#x8BF7;&#x4E86;&#x5185;&#x5B58;&#x5C31;&#x4F1A;&#x7ACB;&#x523B;&#x4F7F;&#x7528;&#xFF0C;&#x5F53;&#x771F;&#x6B63;&#x4F7F;&#x7528;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x7CFB;&#x7EDF;&#x53EF;&#x80FD;&#x5DF2;&#x7ECF;&#x56DE;&#x6536;&#x4E00;&#x90E8;&#x5206;&#x5185;&#x5B58;&#x3002;&#x800C;&#x4E00;&#x65E6;&#x771F;&#x6B63;&#x4F7F;&#x7528;&#x7684;&#x65F6;&#x5019;&#x53D1;&#x73B0;&#x6CA1;&#x6709;&#x5185;&#x5B58;&#xFF0C;&#x7CFB;&#x7EDF;&#x5C06;&#x4F1A;&#x4E3A;&#x4E86;&#x9632;&#x6B62;&#x7CFB;&#x7EDF;&#x8017;&#x5C3D;&#x5185;&#x5B58;&#x800C;&#x89E6;&#x53D1;OOM Killer&#xFF0C;&#x8FD9;&#x4E2A;&#x65F6;&#x5019;&#x5C06;&#x4F1A;&#x8431;&#x855A;&#x6027;&#x7684;&#x6740;&#x6B7B;&#x4E00;&#x4E2A;&#x751A;&#x81F3;&#x591A;&#x4E2A;&#x8FDB;&#x7A0B;&#xFF0C;&#x7528;&#x4E8E;&#x7ED9;&#x65B0;&#x7A0B;&#x5E8F;&#x817E;&#x51FA;&#x7A7A;&#x95F4;&#x3002;</p><p>linux&#x53EF;&#x4EE5;&#x9009;&#x62E9;<code>overcommit</code>&#x7684;&#x7B56;&#x7565;&#xFF0C;&#x751A;&#x81F3;&#x76F4;&#x63A5;&#x7981;&#x7528;<code>overcommit</code>&#x3002;</p><p>&#x4F46;&#x662F;&#x53EA;&#x8981;&#x542F;&#x7528;<code>overcommit</code>&#x7B56;&#x7565;&#xFF0C;&#x90A3;&#x4E48;&#x5FC5;&#x5B9A;&#x4F1A;&#x6709;OOM Killer&#x3002;OOM Killer&#x53EF;&#x4EE5;&#x6839;&#x636E;&#x4E00;&#x4E9B;&#x7528;&#x6237;&#x5B9A;&#x4E49;&#x7684;&#x7B56;&#x7565;&#x6765;&#x51B3;&#x5B9A;&#x54EA;&#x4E9B;&#x8FDB;&#x7A0B;&#x9700;&#x8981;&#x88AB;kill&#x6389;&#x3002;&#x5B83;&#x7684;&#x5E95;&#x5C42;&#x901A;&#x8FC7;<code>/proc/&lt;pid&gt;/oom_score</code>&#x503C;&#x6765;&#x5224;&#x65AD;&#x54EA;&#x4E2A;&#x8FDB;&#x7A0B;&#x9700;&#x8981;&#x88AB;&#x5E72;&#x6389;&#x3002;&#x5982;&#x4E0B;&#x63CF;&#x8FF0;&#x4E00;&#x4E9B;&#x76F8;&#x5173;&#x7B56;&#x7565;&#x4EE5;&#x53CA;&#x5BF9;&#x5E94;&#x6587;&#x4EF6;&#xFF1A;</p><ul><li><code>/proc/&lt;pid&gt;/oom_score_adj</code>&#xFF1A;&#x7528;&#x4E8E;&#x5728;&#x8BA1;&#x7B97;&#x5F97;&#x5230;&#x6700;&#x7EC8;<code>badness score</code>&#x7684;&#x65F6;&#x5019;&#x7D2F;&#x52A0;&#x3002;-1000&#x4EE3;&#x8868;&#x6C38;&#x8FDC;&#x4E0D;&#x4F1A;&#x88AB;kill&#xFF1B;+1000&#x4EE3;&#x8868;&#x6700;&#x5927;&#x53EF;&#x80FD;&#x88AB;kill</li><li><code>/proc/&lt;pid&gt;/oom_adj</code>&#xFF1A;&#x4E3A;&#x4E86;&#x4E0E;&#x65E7;&#x7248;&#x672C;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#x517C;&#x5BB9;&#xFF0C;&#x5199;&#x5165;&#x6216;&#x8005;&#x8BFB;&#x53D6;&#x7684;&#x65F6;&#x5019;&#x4F1A;&#x6309;&#x7167;&#x6BD4;&#x4F8B;&#x5199;&#x5165;&#x8BFB;&#x53D6;&#x5230;<code>oom_score_adj</code>&#x6587;&#x4EF6;&#xFF1B;&#x53EF;&#x80FD;&#x5B58;&#x5728;&#x4E00;&#x5B9A;&#x7684;&#x7CBE;&#x5EA6;&#x4E22;&#x5931;&#x7684;&#x60C5;&#x51B5;&#x53D1;&#x751F;</li><li><code>/proc/&lt;pid&gt;/oom_score</code>&#xFF1A;&#x6700;&#x7EC8;&#x7684;&#x5206;&#x6570;&#xFF0C;&#x7528;&#x4E8E;&#x5224;&#x65AD;&#x54EA;&#x4E2A;&#x8FDB;&#x7A0B;&#x9700;&#x8981;&#x88AB;kill</li></ul><h3 id="OOM-kill&#x7684;&#x5185;&#x6838;&#x5B9E;&#x73B0;"><a href="#OOM-kill&#x7684;&#x5185;&#x6838;&#x5B9E;&#x73B0;" class="headerlink" title="OOM kill&#x7684;&#x5185;&#x6838;&#x5B9E;&#x73B0;"></a>OOM kill&#x7684;&#x5185;&#x6838;&#x5B9E;&#x73B0;</h3><ul><li>&#x5F15;&#x7528;&#x81EA;<a href="https://learning-kernel.readthedocs.io/en/latest/mem-management.html" target="_blank" rel="noopener">&#x5185;&#x5B58;&#x7BA1;&#x7406;</a></li></ul><p>OOM&#x7684;&#x8C03;&#x7528;&#x5173;&#x7CFB;&#xFF1A;<br></p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">__alloc_pages_nodemask -&gt; __alloc_pages_slowpath -&gt; __alloc_pages_may_oom -&gt; out_of_memory -&gt;</span><br><span class="line">__out_of_memory -&gt; select_bad_process -&gt; oom_kill_process</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x5176;&#x903B;&#x8F91;&#x64CD;&#x4F5C;&#x5982;&#x4E0B;&#xFF1A;</p><ol><li>&#x9996;&#x5148;&#x901A;&#x8FC7;&#x51FD;&#x6570; blocking_notifier_call_chain &#x904D;&#x5386;&#x7528;&#x6237;&#x6CE8;&#x518C;&#x7684;&#x901A;&#x77E5;&#x94FE;&#x51FD;&#x6570;&#xFF0C;&#x5982;&#x679C;&#x901A;&#x77E5;&#x94FE;&#x7684;callback&#x51FD;&#x6570;&#x80FD;&#x591F;&#x5904;&#x7406;OOM&#xFF0C;&#x5219;&#x76F4;&#x63A5;&#x9000;&#x51FA;OOM killer&#x64CD;&#x4F5C;&#x3002;</li><li>&#x5982;&#x679C;&#x5F15;&#x8D77;OOM&#x7684;&#x8FDB;&#x7A0B;&#xFF08;current&#xFF09;&#x62E5;&#x6709;pending SIGKILL&#xFF0C;&#x6216;&#x8005;&#x6B63;&#x5728;&#x9000;&#x51FA;&#xFF0C;&#x5219;&#x9009;&#x62E9;current&#x8FDB;&#x7A0B;&#x3002;</li><li>&#x68C0;&#x67E5;&#x53D1;&#x751F;OOM&#x65F6;&#xFF0C;&#x5185;&#x6838;&#x662F;&#x5426;&#x9700;&#x8981;panic&#xFF0C;&#x5982;&#x679C;panic&#xFF0C;&#x8FD9;&#x540E;&#x7EED;&#x4EE3;&#x7801;&#x5C31;&#x4E0D;&#x4F1A;&#x6267;&#x884C;&#x3002;</li><li>&#x5982;&#x679C;&#x8BBE;&#x7F6E;&#x4E86; sysctl_oom_kill_allocating_task &#xFF0C;&#x5E76;&#x4E14; current-&gt;mm &#x4E0D;&#x4E3A;&#x7A7A;&#xFF0C;current&#x7684; oom_score_adj != OOM_SCORE_ADJ_MIN &#xFF0C;&#x4E14;&#x53EF;&#x4EE5;&#x6740;&#x6B7B;current&#xFF0C;&#x5219;&#x76F4;&#x63A5;&#x6740;&#x6B7B;current&#x8FDB;&#x7A0B;&#xFF0C;&#x91CA;&#x653E;&#x5185;&#x5B58;&#x3002;</li><li>&#x8C03;&#x7528; select_bad_process &#x9009;&#x62E9;&#x4E00;&#x4E2A;&#x6700;&#x4F18;&#x7684;&#x8FDB;&#x7A0B;p&#x53BB;&#x6740;</li><li>&#x5982;&#x679C; p == null&#xFF0C; &#x5373;&#x6CA1;&#x6709;&#x8FDB;&#x7A0B;&#x53EF;&#x6740;&#xFF0C;&#x5185;&#x6838;&#x5219;&#x76F4;&#x63A5;panic&#xFF0C;&#x5426;&#x5219;&#x8C03;&#x7528;&#x51FD;&#x6570; oom_kill_process &#x53BB;kill&#x9009;&#x62E9;&#x9009;&#x62E9;&#x7684;&#x8FDB;&#x7A0B;p&#x3002;</li></ol><p><code>select_bad_process</code>&#x64CD;&#x4F5C;&#xFF1A;</p><ol><li>&#x8BE5;&#x51FD;&#x6570;&#x904D;&#x5386;&#x6240;&#x6709;&#x7684;&#x8FDB;&#x7A0B;&#x548C;&#x7EBF;&#x7A0B; for_each_process_thread(g, p)</li><li>&#x9488;&#x5BF9;&#x6BCF;&#x4E00;&#x4E2A;&#x7EBF;&#x7A0B;&#xFF1A;&#x8BE5;&#x51FD;&#x6570;&#x5148;&#x5229;&#x7528; oom_scan_process_thread &#x68C0;&#x67E5;&#x7EBF;&#x7A0B;&#x7684;&#x7C7B;&#x522B;&#xFF0C;&#x6392;&#x9664;&#x4E00;&#x4E9B;&#x7279;&#x6B8A;&#x7684;&#x7EBF;&#x7A0B;&#xFF0C;&#x7136;&#x540E;&#x5BF9;&#x53EF;&#x4EE5;&#x4F5C;&#x4E3A;&#x5019;&#x9009;&#x7684;&#x7EBF;&#x7A0B;&#x8FDB;&#x884C;&#x8BC4;&#x5206;&#x3002;</li><li>&#x6700;&#x540E;&#x8FD4;&#x56DE;&#x8BC4;&#x5206;&#x6700;&#x9AD8;&#x7684;&#x7EBF;&#x7A0B;&#x3002;</li></ol><p>&#x6CE8;&#x610F;&#xFF1A;&#x7B2C;2&#x6B65;&#x9AA4;&#x4E2D;&#xFF0C;&#x6392;&#x9664;&#x7684;&#x7EBF;&#x7A0B;&#x5305;&#x62EC;&#xFF1A;</p><ul><li>init&#x8FDB;&#x7A0B;</li><li>kernel thread&#x7EBF;&#x7A0B;</li><li>&#x8FDB;&#x7A0B;&#x6CA1;&#x6709;&#x53EF;&#x4EE5;&#x91CA;&#x653E;&#x7684;&#x5185;&#x5B58;</li><li>&#x4E0D;&#x662F;&#x5F15;&#x8D77;oom&#x7684;memcg&#x4E2D;&#x7684;&#x8FDB;&#x7A0B;</li><li>&#x8FDB;&#x7A0B;&#x6B63;&#x88AB;OOM kill</li><li>&#x2026;</li></ul><h3 id="&#x5982;&#x4F55;&#x9632;&#x6B62;&#x8FDB;&#x7A0B;&#x88AB;Kill"><a href="#&#x5982;&#x4F55;&#x9632;&#x6B62;&#x8FDB;&#x7A0B;&#x88AB;Kill" class="headerlink" title="&#x5982;&#x4F55;&#x9632;&#x6B62;&#x8FDB;&#x7A0B;&#x88AB;Kill"></a>&#x5982;&#x4F55;&#x9632;&#x6B62;&#x8FDB;&#x7A0B;&#x88AB;Kill</h3><ul><li><code>/proc/&lt;pid&gt;/oom_score_adj</code>&#x8BBE;&#x7F6E;&#x503C;&#x4E3A;-1000</li><li><code>/proc/&lt;pid&gt;/oom_adj</code>&#x8BBE;&#x7F6E;&#x503C;&#x4E3A;-17</li><li>&#x5B8C;&#x5168;&#x5173;&#x95ED;OOM Killer&#xFF0C;<code># sysctl -w vm.overcommit_memory=2 # echo &quot;vm.overcommit_memory=2&quot; &gt;&gt; /etc/sysctl.conf</code>&#xFF0C;&#x4E0D;&#x63A8;&#x8350;&#x7528;&#x4E8E;&#x751F;&#x4EA7;&#x73AF;&#x5883;&#x3002;&#x53EF;&#x80FD;&#x9020;&#x6210;&#x5185;&#x5B58;&#x6DF7;&#x4E71;&#x3002;</li></ul><h3 id="&#x603B;&#x7ED3;"><a href="#&#x603B;&#x7ED3;" class="headerlink" title="&#x603B;&#x7ED3;"></a>&#x603B;&#x7ED3;</h3><ul><li>&#x5BF9;&#x4E8E;&#x670D;&#x52A1;&#x8FDB;&#x7A0B;&#xFF0C;&#x9700;&#x8981;&#x9488;&#x5BF9;&#x6027;&#x505A;&#x4E00;&#x4E9B;&#x63AA;&#x65BD;&#xFF0C;&#x9632;&#x6B62;&#x7531;&#x4E8E;&#x67D0;&#x4E9B;&#x539F;&#x56E0;&#x9020;&#x6210;&#x7684;&#x5185;&#x5B58;OOM&#x60C5;&#x51B5;&#x3002;</li><li>&#x5728;&#x65E5;&#x5FD7;&#x6253;&#x5370;&#x4E0A;&#xFF0C;&#x8FD8;&#x9700;&#x8981;&#x63A7;&#x5236;&#x5355;&#x65E5;&#x5FD7;&#x6587;&#x4EF6;&#x7684;&#x5927;&#x5C0F;&#xFF0C;&#x8D85;&#x8FC7;&#x7684;&#x505A;&#x5206;&#x5272;</li></ul><h3 id="&#x53C2;&#x8003;&#x8D44;&#x6599;"><a href="#&#x53C2;&#x8003;&#x8D44;&#x6599;" class="headerlink" title="&#x53C2;&#x8003;&#x8D44;&#x6599;"></a>&#x53C2;&#x8003;&#x8D44;&#x6599;</h3><ul><li><a href="https://learning-kernel.readthedocs.io/en/latest/mem-management.html" target="_blank" rel="noopener">&#x5185;&#x5B58;&#x7BA1;&#x7406; &#x2014; &#x5185;&#x6838;&#x77E5;&#x8BC6; v0.1 documentation</a></li><li><a href="https://unix.stackexchange.com/questions/153585/how-does-the-oom-killer-decide-which-process-to-kill-first" target="_blank" rel="noopener">linux - How does the OOM killer decide which process to kill first? - Unix &amp; Linux Stack Exchange</a></li></ul><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;今日在线上linux查看日志追踪一个问题的时候，钉钉突然接收到告警信息，提示服务crash。&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="JVM" scheme="https://xuqiang.me/categories/Java/JVM/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="jvm" scheme="https://xuqiang.me/tags/jvm/"/>
    
      <category term="linux" scheme="https://xuqiang.me/tags/linux/"/>
    
      <category term="oom" scheme="https://xuqiang.me/tags/oom/"/>
    
  </entry>
  
  <entry>
    <title>JSR269插件化注解API</title>
    <link href="https://xuqiang.me/JSR269%E6%8F%92%E4%BB%B6%E5%8C%96%E6%B3%A8%E8%A7%A3API.html"/>
    <id>https://xuqiang.me/JSR269插件化注解API.html</id>
    <published>2019-05-07T15:41:47.000Z</published>
    <updated>2019-06-23T08:39:31.279Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x4E00;&#x76F4;&#x5728;&#x4F7F;&#x7528;Lombok&#x4EE5;&#x53CA;MapStruct&#xFF0C;&#x4F46;&#x662F;&#x5BF9;&#x4E8E;&#x5B83;&#x4EEC;&#x80FD;&#x591F;&#x5728;&#x7F16;&#x8BD1;&#x9636;&#x6BB5;&#x76F4;&#x63A5;&#x751F;&#x6210;&#x5B9E;&#x4F8B;&#x4EE3;&#x7801;&#x5374;&#x6CA1;&#x6709;&#x4ED4;&#x7EC6;&#x4E86;&#x89E3;&#x8FC7;&#x3002;&#x6700;&#x8FD1;&#x521A;&#x597D;&#x5728;&#x90E8;&#x95E8;&#x5185;&#x505A;&#x4E86;&#x4E00;&#x6B21;&#x5206;&#x4EAB;&#xFF0C;&#x4E5F;&#x5728;&#x8FD9;&#x91CC;&#x5BF9;&#x5177;&#x4F53;&#x539F;&#x7406;&#x505A;&#x4E00;&#x4E2A;&#x8BE6;&#x7EC6;&#x9610;&#x8FF0;&#x3002;</p><a id="more"></a><h3 id="Lombok&#x4EE5;&#x53CA;MapStruct&#x5B9E;&#x73B0;&#x5927;&#x4F53;&#x601D;&#x8DEF;"><a href="#Lombok&#x4EE5;&#x53CA;MapStruct&#x5B9E;&#x73B0;&#x5927;&#x4F53;&#x601D;&#x8DEF;" class="headerlink" title="Lombok&#x4EE5;&#x53CA;MapStruct&#x5B9E;&#x73B0;&#x5927;&#x4F53;&#x601D;&#x8DEF;"></a>Lombok&#x4EE5;&#x53CA;MapStruct&#x5B9E;&#x73B0;&#x5927;&#x4F53;&#x601D;&#x8DEF;</h3><p>Lombok&#x4EE5;&#x53CA;MapStruct&#x90FD;&#x662F;&#x901A;&#x8FC7;&#x5728;&#x76EE;&#x6807;&#x4EE3;&#x7801;&#x4E0A;&#x6807;&#x8BB0;&#x6CE8;&#x89E3;&#xFF0C;&#x7F16;&#x8BD1;&#x5668;&#x80FD;&#x591F;&#x6839;&#x636E;&#x6CE8;&#x89E3;&#x751F;&#x6210;&#x5BF9;&#x5E94;&#x7684;&#x5B9E;&#x73B0;&#x4EE3;&#x7801;&#x3002;&#x6BD4;&#x5982;Lombok&#x5728;&#x5C5E;&#x6027;&#x4E0A;&#x6807;&#x8BB0;<code>@Getter</code>&#xFF0C;&#x90A3;&#x4E48;&#x5728;&#x8FD9;&#x4E2A;<code>Java Bean</code>&#x5185;&#x5C31;&#x4F1A;&#x751F;&#x6210;&#x5BF9;&#x5E94;&#x5C5E;&#x6027;&#x7684;<code>get</code>&#x65B9;&#x6CD5;&#x3002;</p><p>&#x672C;&#x8D28;&#x4E0A;&#x6765;&#x8BF4;&#xFF0C;&#x4E0D;&#x7BA1;&#x662F;Lombok&#x6216;&#x8005;MapStruct&#xFF0C;&#x90FD;&#x662F;&#x901A;&#x8FC7;Java&#x7684;&#x4E00;&#x4E2A;&#x6807;&#x51C6;API&#x6765;&#x5B9E;&#x73B0;&#x7684;&#xFF1B;&#x8FD9;&#x4E2A;API&#x5373;&#x4E3A;<code>Pluggable Annotation Processing API</code>&#xFF0C;&#x7B80;&#x79F0;&#x4E3A;JSR269&#x3002;</p><h3 id="JSR269"><a href="#JSR269" class="headerlink" title="JSR269"></a>JSR269</h3><p>&#x501F;&#x7528;JSR269&#x5B98;&#x65B9;&#x539F;&#x6587;&#x5B9A;&#x4E49;&#xFF08;&#x9644;&#x5E26;&#x539F;&#x6587;&#x5730;&#x5740;&#xFF1A;<a href="https://jcp.org/en/jsr/detail?id=269&#xFF09;&#xFF1A;" target="_blank" rel="noopener">https://jcp.org/en/jsr/detail?id=269&#xFF09;&#xFF1A;</a></p><blockquote><p>J2SE 1.5 added a new Java language mechanism &#x201C;annotations&#x201D; that allows annotation types to be used to annotate classes, fields, and methods. These annotations are typically processed either by build-time tools or by run-time libraries to achieve new semantic effects. In order to support annotation processing at build-time, this JSR will define APIs to allow annotation processors to be created using a standard pluggable API. This will simplify the task of creating annotation processors and will also allow automation of the discovery of appropriate annotation processors for a given source file.<br>The specification will include at least two sections, a section of API modeling the Java programming language and a distinct section for declaring annotation processors and controlling how they are run. Since annotations are placed on program elements, an annotation processing framework needs to reflect program structure. Annotation processors will be able to specify what annotations they process and multiple processors will be able to run cooperatively.<br>The processors and program structure api can be accessed at build-time; i.e. this functionality supplements core reflection support for reading annotations.</p></blockquote><p>&#x8BD1;&#x6587;&#x5982;&#x4E0B;&#xFF1A;</p><blockquote><p>J2SE 1.5 &#x589E;&#x52A0;&#x4E86;&#x4E00;&#x79CD;&#x65B0;&#x7684;Java&#x8BED;&#x8A00;&#x673A;&#x5236;&#x201D;annotations&#x201C;&#xFF0C;&#x5B83;&#x5141;&#x8BB8;&#x6CE8;&#x89E3;&#x88AB;&#x7528;&#x4E8E;&#x7C7B;&#x3001;&#x5B57;&#x6BB5;&#x4EE5;&#x53CA;&#x65B9;&#x6CD5;&#x4E0A;&#x3002;&#x8FD9;&#x4E9B;&#x6CE8;&#x89E3;&#x7531; <code>build-time</code> &#x5DE5;&#x5177;&#x4EE5;&#x53CA; <code>run-time</code> &#x5E93;&#x5904;&#x7406;&#xFF0C;&#x6765;&#x8FBE;&#x5230;&#x65B0;&#x7684;&#x8BED;&#x4E49;&#x6548;&#x679C;&#x3002;&#x4E3A;&#x4E86;&#x652F;&#x6301;&#x5728; <code>build-time</code> &#x65F6;&#x5904;&#x7406;&#x6CE8;&#x89E3;&#xFF0C;&#x8FD9;&#x4E2A;JSR&#x5B9A;&#x4E49;&#x4E86;&#x901A;&#x7528;&#x7684;&#x63D2;&#x5165;&#x5F0F;API&#x7528;&#x4E8E;&#x521B;&#x5EFA;&#x6807;&#x51C6;&#x7684;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x3002;&#x8FD9;&#x5C06;&#x7B80;&#x5316;&#x521B;&#x5EFA;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x7684;&#x4EFB;&#x52A1;&#xFF0C;&#x5E76;&#x4E14;&#x8FD8;&#x80FD;&#x591F;&#x6839;&#x636E;&#x6E90;&#x6587;&#x4EF6;&#x81EA;&#x52A8;&#x5339;&#x914D;&#x54CD;&#x5E94;&#x7684;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x3002;<br>&#x8BE5;&#x89C4;&#x8303;&#x5C06;&#x81F3;&#x5C11;&#x5305;&#x542B;&#x4E24;&#x4E2A;&#x90E8;&#x5206;&#xFF0C;&#x4E00;&#x90E8;&#x5206;&#x7528;&#x4E8E;&#x5EFA;&#x6A21;Java&#x7F16;&#x7A0B;&#x8BED;&#x8A00;&#x7684;API&#xFF0C;&#x53E6;&#x4E00;&#x90E8;&#x5206;&#x7528;&#x4E8E;&#x58F0;&#x660E;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x4EE5;&#x53CA;&#x4ED6;&#x4EEC;&#x7684;&#x8FD0;&#x4F5C;&#x673A;&#x5236;&#x3002;&#x7531;&#x4E8E;&#x6CE8;&#x89E3;&#x88AB;&#x7528;&#x4E8E;&#x7A0B;&#x5E8F;&#x5143;&#x7D20;&#x4E0A;&#xFF0C;&#x4E00;&#x4E2A;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x6846;&#x67B6;&#x9700;&#x8981;&#x53CD;&#x6620;&#x7A0B;&#x5E8F;&#x7ED3;&#x6784;&#x3002;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x5C06;&#x80FD;&#x6307;&#x5B9A;&#x54EA;&#x4E9B;&#x6CE8;&#x89E3;&#x662F;&#x5B83;&#x4EEC;&#x53EF;&#x4EE5;&#x5904;&#x7406;&#x7684;&#xFF0C;&#x4EE5;&#x53CA;&#x591A;&#x4E2A;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x5982;&#x4F55;&#x534F;&#x540C;&#x5DE5;&#x4F5C;&#x3002;<br>&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x4EE5;&#x53CA;&#x7A0B;&#x5E8F;&#x6846;&#x67B6;api&#x53EF;&#x4EE5;&#x5728; <code>build-time</code> &#x65F6;&#x8BBF;&#x95EE;&#xFF1B;&#x4E3E;&#x4E2A;&#x4F8B;&#x5B50;&#xFF0C;&#x6B64;&#x529F;&#x80FD;&#x63D0;&#x4F9B;&#x4E86;&#x6838;&#x5FC3;&#x53CD;&#x5C04;&#x652F;&#x6301;&#x7528;&#x4E8E;&#x8BFB;&#x53D6;&#x6CE8;&#x89E3;&#xFF08;&#x6CE8;&#xFF1A;&#x4E00;&#x822C;&#x6307;&#x4ECE;&#x6E90;&#x7801;&#x5185;&#x8BFB;&#x53D6;&#x6CE8;&#x89E3;&#x6216;&#x8005;&#x53EA;&#x8BFB;&#x53D6;&#x6807;&#x6CE8;&#x4E3A;<code>source-only</code>&#x7684;&#x6CE8;&#x89E3;&#xFF09;&#x3002;</p></blockquote><p>&#x5373;&#xFF0C;&#x5728;J2SE 1.6&#x7248;&#x672C;&#x52A0;&#x5165;&#x7684;JSR269&#x7684;&#x4E3B;&#x8981;&#x70B9;&#x5982;&#x4E0B;&#xFF1A;</p><ul><li>&#x4E13;&#x95E8;&#x7528;&#x4E8E;&#x652F;&#x6301; J2SE 1.5 &#x65E0;&#x6CD5;&#x5904;&#x7406;&#x7684; <code>build-time</code> &#x6CE8;&#x89E3;&#x5904;&#x7406;&#x573A;&#x666F;&#xFF0C;&#x5E76;&#x5B9A;&#x4E49;&#x901A;&#x7528;&#x6CE8;&#x89E3;&#x5904;&#x7406;API</li><li>&#x5F15;&#x5165;&#x7A0B;&#x5E8F;&#x6846;&#x67B6;api</li></ul><h3 id="JSR269&#x8FD0;&#x884C;&#x673A;&#x5236;"><a href="#JSR269&#x8FD0;&#x884C;&#x673A;&#x5236;" class="headerlink" title="JSR269&#x8FD0;&#x884C;&#x673A;&#x5236;"></a>JSR269&#x8FD0;&#x884C;&#x673A;&#x5236;</h3><pre class="mermaid">sequenceDiagram;  javac/Main-&gt;&gt;javac/Main: new main.Main(&quot;javac)  javac/Main-&gt;&gt;main/Main: &#x7F16;&#x8BD1;&#x53C2;&#x6570;&#x4F20;&#x9012;  main/Main-&gt;&gt;main/Main: Javac&#x4E0A;&#x4E0B;&#x6587;&#x521B;&#x5EFA;  main/Main-&gt;&gt;main/Main: JavaFileManager.preRegister&#x9884;&#x6CE8;&#x518C;  main/Main-&gt;&gt;main/Main: &#x6267;&#x884C;compile&#x5E76;&#x4F20;&#x9012;&#x7F16;&#x8BD1;&#x53C2;&#x6570;&#x4EE5;&#x53CA;&#x4E0A;&#x4E0B;&#x6587;  main/Main--&gt;&gt;javac/Main: &#x53C2;&#x6570;&#x6709;&#x8BEF;&#x663E;&#x793A;&#x5E2E;&#x52A9;&#x4FE1;&#x606F;  main/Main-&gt;&gt;main/Main: &#x53C2;&#x6570;&#x89E3;&#x6790;(&#x83B7;&#x53D6;class&#x4EE5;&#x53CA;files&#x5E76;&#x521D;&#x59CB;&#x5316;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x8DEF;&#x5F84;)  alt &#x89E3;&#x6790;&#x7684;&#x6587;&#x4EF6;&#x4E3A;&#x7A7A;&#x4E14;&#x542B;&#x6709;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x53C2;&#x6570;    main/Main--&gt;&gt;javac/Main: &#x65E0;source.files.classes  else &#x5B58;&#x5728;&#x6587;&#x4EF6;&#x6216;&#x8005;&#x65E0;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x53C2;&#x6570;    main/Main-&gt;&gt;main/Main: JavaCompiler&#x5B9E;&#x4F8B;&#x521B;&#x5EFA;    main/Main-&gt;&gt;main/JavaCompiler: &#x4F20;&#x9012;&#x6E90;&#x6587;&#x4EF6;&#x5217;&#x8868;&#x4EE5;&#x53CA;&#x7C7B;&#x5217;&#x8868;    alt PROC&#x4E3A;none&#x503C;      main/JavaCompiler-&gt;&gt;main/JavaCompiler: &#x4E0D;&#x521D;&#x59CB;&#x5316;    else PROC&#x975E;none&#x503C;      main/JavaCompiler-&gt;&gt;main/JavaCompiler: &#x521D;&#x59CB;&#x5316;&#x6CE8;&#x89E3;      main/JavaCompiler-&gt;&gt;processing/JavaProcessingEnvironment: &#x8BBE;&#x7F6E;Processors      processing/JavaProcessingEnvironment-&gt;&gt;processing/JavaProcessingEnvironment: &#x4ECE;&#x53C2;&#x6570;&#x83B7;&#x53D6;processors      processing/JavaProcessingEnvironment-&gt;&gt;processing/JavaProcessingEnvironment: processors&#x521D;&#x59CB;&#x5316;&#x5E76;&#x8D4B;&#x503C;&#x7ED9;discoveredProcs    end    main/JavaCompiler-&gt;&gt;main/JavaCompiler: &#x5904;&#x7406;&#x6CE8;&#x89E3;    main/JavaCompiler-&gt;&gt;main/JavaCompiler: &#x5C06;&#x9700;&#x8981;&#x7684;package&#x6CE8;&#x89E3;&#x4EE5;&#x53CA;class&#x6CE8;&#x89E3;&#x52A0;&#x5165;&#x5F85;&#x5904;&#x7406;&#x5217;&#x8868;    main/JavaCompiler-&gt;&gt;processing/JavaProcessingEnvironment: &#x4F20;&#x9012;&#x4E0A;&#x4E0B;&#x6587;&#x3001;&#x5F85;&#x5904;&#x7406;&#x7684;&#x5305;&#x7C7B;&#x6CE8;&#x89E3;&#x5217;&#x8868;    processing/JavaProcessingEnvironment-&gt;&gt;processing/JavaProcessingEnvironment: &#x6784;&#x9020;Round    loop &#x5FAA;&#x73AF;&#x76F4;&#x5230;&#x6CA1;&#x6709;&#x65B0;&#x6587;&#x4EF6;&#x4EA7;&#x751F;(moreToDo&#x65B9;&#x6CD5;)      processing/JavaProcessingEnvironment-&gt;&gt;processing/Round: &#x6784;&#x9020;JavacRoundEnvironment&#xFF0C;&#x4F20;&#x9012;&#x5305;&#x7C7B;      processing/Round-&gt;&gt;processing/Round: &#x901A;&#x8FC7;&#x9876;&#x5C42;&#x7684;&#x5305;&#x7C7B;&#x627E;&#x5230;&#x6240;&#x6709;&#x652F;&#x6301;&#x7684;&#x6CE8;&#x89E3;      loop &#x5FAA;&#x73AF;discoveredProcs        processing/Round-&gt;&gt;processing/Round: &#x901A;&#x8FC7;&#x53D8;&#x91CF;annotationsPresent&#x5224;&#x65AD;&#x8FD9;&#x4E2A;&#x6CE8;&#x89E3;&#x662F;&#x5426;&#x652F;&#x6301;        alt &#x6CE8;&#x89E3;&#x652F;&#x6301;          processing/Round-&gt;&gt;processing/Round: &#x52A0;&#x5165;&#x5F85;&#x5904;&#x7406;&#x5217;&#x8868;&#xFF1B;matchedNames&#x6DFB;&#x52A0;&#x652F;&#x6301;&#x7684;&#x6CE8;&#x89E3;&#x540D;        else &#x6CE8;&#x89E3;&#x4E0D;&#x652F;&#x6301;          processing/Round-&gt;&gt;processing/Round: &#x4E0D;&#x505A;&#x5904;&#x7406;&#xFF0C;&#x7EE7;&#x7EED;&#x4E0B;&#x4E00;&#x6B65;        end        alt matchedNames&#x662F;&#x5426;&#x4E0D;&#x4E3A;&#x7A7A;&#x4E14;&#x5904;&#x7406;&#x5668;&#x662F;&#x5426;&#x5DF2;&#x88AB;&#x6267;&#x884C;          processing/Round-&gt;&gt;processing/Round: &#x8C03;&#x7528;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x7684;process&#x65B9;&#x6CD5;          processing/Round-&gt;&gt;processing/Round: &#x6807;&#x8BB0;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x5DF2;&#x88AB;&#x6267;&#x884C;          alt &#x6267;&#x884C;&#x7ED3;&#x679C;&#x662F;&#x4E3A;true            processing/Round-&gt;&gt;processing/Round: unmatchedAnnotations&#x79FB;&#x9664;matchedNames&#x5185;&#x6240;&#x6709;&#x5339;&#x914D;&#x7684;&#x9879;          else &#x6267;&#x884C;&#x7ED3;&#x679C;&#x4E3A;false            processing/Round-&gt;&gt;processing/Round: &#x4E0D;&#x505A;&#x5904;&#x7406;&#xFF0C;&#x7EE7;&#x7EED;&#x4E0B;&#x4E00;&#x6B65;          end        else           processing/Round-&gt;&gt;processing/Round: &#x4E0D;&#x505A;&#x5904;&#x7406;&#xFF0C;&#x7EE7;&#x7EED;&#x4E0B;&#x4E00;&#x6B65;        end      end      processing/Round--&gt;&gt;processing/JavaProcessingEnvironment: &#x4E00;&#x6B21;round&#x5FAA;&#x73AF;&#x5B8C;&#x6210;      processing/JavaProcessingEnvironment-&gt;&gt;processing/JavaProcessingEnvironment: &#x6784;&#x5EFA;&#x4E0B;&#x4E00;&#x4E2A;round    end    processing/JavaProcessingEnvironment-&gt;&gt;processing/Round: &#x6267;&#x884C;&#x6700;&#x540E;&#x4E00;&#x6B21;run&#x65B9;&#x6CD5;    processing/Round-&gt;&gt;processing/DiscoveredProcessors: &#x6240;&#x6709;&#x6267;&#x884C;&#x8FC7;&#x7684;processor&#x4F1A;&#x5E26;&#x4E0A;&#x7A7A;&#x6CE8;&#x89E3;&#x96C6;&#x5408;&#x53C2;&#x6570;&#x518D;&#x6B21;&#x6267;&#x884C;&#x4E00;&#x904D;    processing/DiscoveredProcessors--&gt;&gt;processing/Round: &#x5B8C;&#x6210;&#x6267;&#x884C;    processing/Round--&gt;&gt;processing/JavaProcessingEnvironment: &#x5B8C;&#x6210;&#x6700;&#x540E;&#x4E00;&#x6B21;round    processing/JavaProcessingEnvironment-&gt;&gt;processing/JavaProcessingEnvironment: &#x5224;&#x65AD;&#x672C;&#x6B21;&#x662F;&#x5426;&#x5B58;&#x5728;&#x9519;&#x8BEF;&#xFF0C;&#x5B58;&#x5728;&#x5219;&#x6807;&#x8BB0;errorStatus    processing/JavaProcessingEnvironment-&gt;&gt;processing/JavaProcessingEnvironment: &#x6E05;&#x7406;&#x6240;&#x6709;&#x5305;&#x7C7B;    processing/JavaProcessingEnvironment-&gt;&gt;processing/JavaProcessingEnvironment: &#x6784;&#x5EFA;&#x4E3A;&#x6700;&#x7EC8;&#x7F16;&#x8BD1;&#x4F7F;&#x7528;&#x7684;JavaCompiler    alt errorStatus&#x72B6;&#x6001;&#x4E3A;true      processing/JavaProcessingEnvironment-&gt;&gt;processing/JavaProcessingEnvironment: &#x9519;&#x8BEF;&#x6570;&#x4E0D;&#x4E3A;0&#x8FD4;&#x56DE;&#x7F16;&#x8BD1;&#x5668;      processing/JavaProcessingEnvironment-&gt;&gt;processing/JavaProcessingEnvironment: &#x9519;&#x8BEF;&#x6570;&#x4E3A;0&#x65E5;&#x5FD7;&#x8BB0;&#x5F55;&#x65E0;&#x9519;&#x8BEF;+1    else erroStatus&#x72B6;&#x6001;&#x4E3A;false      processing/JavaProcessingEnvironment-&gt;&gt;processing/JavaProcessingEnvironment: enterTrees    end    processing/JavaProcessingEnvironment--&gt;&gt;main/JavaCompiler: &#x8FD4;&#x56DE;&#x7F16;&#x8BD1;&#x5668;    main/JavaCompiler--&gt;&gt;main/Main: &#x6267;&#x884C;&#x7F16;&#x8BD1;&#x5B8C;&#x6210;    alt &#x9519;&#x8BEF;&#x6570;&#x5927;&#x4E8E;0      main/Main--&gt;&gt;javac/Main: &#x6267;&#x884C;&#x9519;&#x8BEF;    else &#x4E3A;&#x7A7A;      main/Main--&gt;&gt;javac/Main: &#x6267;&#x884C;&#x6B63;&#x786E;    end  end</pre><h3 id="&#x6837;&#x4F8B;"><a href="#&#x6837;&#x4F8B;" class="headerlink" title="&#x6837;&#x4F8B;"></a>&#x6837;&#x4F8B;</h3><p>&#x6784;&#x5EFA;&#x4E09;&#x4E2A;&#x6A21;&#x5757;&#xFF1A;</p><ol><li>&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x7C7B;&#x4EE5;&#x53CA;&#x76EE;&#x6807;&#x6CE8;&#x89E3;&#x7C7B;</li><li>&#x6CE8;&#x89E3;&#x6CE8;&#x518C;&#x4E3A;&#x670D;&#x52A1;</li><li>&#x8C03;&#x7528;&#x65B9;</li></ol><h4 id="&#x6CE8;&#x89E3;&#x7C7B;&#x4EE5;&#x53CA;&#x5904;&#x7406;&#x7C7B;"><a href="#&#x6CE8;&#x89E3;&#x7C7B;&#x4EE5;&#x53CA;&#x5904;&#x7406;&#x7C7B;" class="headerlink" title="&#x6CE8;&#x89E3;&#x7C7B;&#x4EE5;&#x53CA;&#x5904;&#x7406;&#x7C7B;"></a>&#x6CE8;&#x89E3;&#x7C7B;&#x4EE5;&#x53CA;&#x5904;&#x7406;&#x7C7B;</h4><p>&#x6CE8;&#x89E3;&#x7C7B;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Target</span>({ElementType.METHOD, ElementType.TYPE})</span><br><span class="line"><span class="meta">@Retention</span>(RetentionPolicy.SOURCE)</span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> Test {</span><br><span class="line"></span><br><span class="line">    <span class="function">String <span class="title">value</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x7C7B;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SupportedAnnotationTypes</span>(value = {<span class="string">&quot;com.whatakitty.learn.jsr269.Test&quot;</span>})</span><br><span class="line"><span class="meta">@SupportedSourceVersion</span>(value = SourceVersion.RELEASE_8)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AnnotationProcessor</span> <span class="keyword">extends</span> <span class="title">AbstractProcessor</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Messager messager;</span><br><span class="line">    <span class="keyword">private</span> AtomicInteger atomicInteger;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">(ProcessingEnvironment env)</span> </span>{</span><br><span class="line">        messager = env.getMessager();</span><br><span class="line">        atomicInteger = <span class="keyword">new</span> AtomicInteger(<span class="number">0</span>);</span><br><span class="line">        <span class="keyword">super</span>.init(env);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">process</span><span class="params">(Set&lt;? extends TypeElement&gt; annotations, RoundEnvironment roundEnv)</span> </span>{</span><br><span class="line">        messager.printMessage(Diagnostic.Kind.NOTE, <span class="string">&quot;Hello World!&quot;</span> + atomicInteger.incrementAndGet());</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><h4 id="&#x6CE8;&#x518C;&#x670D;&#x52A1;"><a href="#&#x6CE8;&#x518C;&#x670D;&#x52A1;" class="headerlink" title="&#x6CE8;&#x518C;&#x670D;&#x52A1;"></a>&#x6CE8;&#x518C;&#x670D;&#x52A1;</h4><p>&#x5728;&#x6587;&#x4EF6;&#x5939;<code>resources/META-INF/services</code>&#x4E0B;&#x521B;&#x5EFA;&#x6587;&#x4EF6;<code>javax.annotation.processing.Processor</code>&#xFF0C;&#x5185;&#x5BB9;&#x5982;&#x4E0B;&#xFF1A;<br></p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">com.whatakitty.learn.jsr269.AnnotationProcessor</span><br></pre></td></tr></tbody></table></figure><p></p><h4 id="&#x8C03;&#x7528;&#x65B9;"><a href="#&#x8C03;&#x7528;&#x65B9;" class="headerlink" title="&#x8C03;&#x7528;&#x65B9;"></a>&#x8C03;&#x7528;&#x65B9;</h4><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test1</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>{</span><br><span class="line">        System.out.println(<span class="string">&quot;success&quot;</span>);</span><br><span class="line">        test();</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span>(<span class="string">&quot;method is test&quot;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">test</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>{</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h4 id="&#x8FD0;&#x884C;&#x7ED3;&#x679C;"><a href="#&#x8FD0;&#x884C;&#x7ED3;&#x679C;" class="headerlink" title="&#x8FD0;&#x884C;&#x7ED3;&#x679C;"></a>&#x8FD0;&#x884C;&#x7ED3;&#x679C;</h4><p><img src="https://static.xuqiang.me/public/images/191455.jpg" alt="javac-annotation-pluggable-api&#x8FD0;&#x884C;&#x7ED3;&#x679C;"></p><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#xFF0C;&#x4E0A;&#x56FE;&#x4E2D;&#x5DF2;&#x7ECF;&#x8F93;&#x51FA;&#x4E24;&#x6B21;<strong>Hello World!</strong>&#x3002;&#x81F3;&#x4E8E;&#x4E3A;&#x4EC0;&#x4E48;&#x4F1A;&#x8F93;&#x51FA;&#x4E24;&#x6B21;&#xFF0C;&#x662F;&#x7531;&#x4E8E;&#x7B2C;&#x4E00;&#x6B21;&#x662F;&#x672C;&#x8EAB;&#x6CE8;&#x89E3;&#x7684;&#x5904;&#x7406;&#x8C03;&#x7528;&#xFF1B;&#x6700;&#x540E;&#x4E00;&#x6B21;&#x662F;&#xFF0C;jdk&#x4F1A;&#x5728;&#x6240;&#x6709;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5B8C;&#x6210;&#x540E;&#xFF0C;&#x5C06;&#x6240;&#x6709;&#x5904;&#x7406;&#x8FC7;&#x7684;&#x6CE8;&#x89E3;&#x5168;&#x90E8;&#x4F20;&#x5165;&#x7A7A;&#x6CE8;&#x89E3;&#x518D;&#x6B21;&#x6267;&#x884C;&#x4E00;&#x904D;&#xFF0C;&#x4EE3;&#x7801;&#x5982;&#x4E0B;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * Run all remaining processors on the procStateList that</span></span><br><span class="line"><span class="comment">  * have not already run this round with an empty set of</span></span><br><span class="line"><span class="comment">  * annotations.</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">runContributingProcs</span><span class="params">(RoundEnvironment re)</span> </span>{</span><br><span class="line">  <span class="keyword">if</span> (!onProcInterator) {</span><br><span class="line">    <span class="comment">// &#x6784;&#x9020;&#x7A7A;&#x7684;&#x6CE8;&#x89E3;&#x5143;&#x7D20;&#x96C6;&#x5408;</span></span><br><span class="line">    Set&lt;TypeElement&gt; emptyTypeElements = Collections.emptySet();</span><br><span class="line">    <span class="comment">// &#x904D;&#x5386;&#x6240;&#x6709;&#x6CE8;&#x518C;&#x7684;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;</span></span><br><span class="line">    <span class="keyword">while</span>(innerIter.hasNext()) {</span><br><span class="line">        ProcessorState ps = innerIter.next();</span><br><span class="line">        <span class="comment">// &#x5224;&#x65AD;&#x8BE5;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;&#x662F;&#x5426;&#x5728;&#x4E4B;&#x524D;&#x5904;&#x7406;&#x8FC7;&#x6CE8;&#x89E3;&#xFF0C;&#x672A;&#x53C2;&#x4E0E;&#x8FC7;&#x7684;&#x4E0D;&#x4F1A;&#x8C03;&#x7528;</span></span><br><span class="line">        <span class="keyword">if</span> (ps.contributed)</span><br><span class="line">          <span class="comment">// &#x4F20;&#x5165;&#x7A7A;&#x7684;&#x6CE8;&#x89E3;&#x5143;&#x7D20;&#x96C6;&#x5408;&#xFF0C;&#x91CD;&#x65B0;&#x8C03;&#x7528;&#x4E00;&#x6B21;&#x6CE8;&#x89E3;&#x5904;&#x7406;&#x5668;</span></span><br><span class="line">          callProcessor(ps.processor, emptyTypeElements, re);</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><h3 id="Lombok&#x539F;&#x7406;"><a href="#Lombok&#x539F;&#x7406;" class="headerlink" title="Lombok&#x539F;&#x7406;"></a>Lombok&#x539F;&#x7406;</h3><p>Lombok&#x57FA;&#x4E8E;JSR269 API&#x5B9E;&#x73B0;&#x4E86;&#x901A;&#x8FC7;&#x7279;&#x5B9A;&#x6CE8;&#x89E3;&#x751F;&#x6210;&#x5BF9;&#x5E94;&#x4EE3;&#x7801;&#x7684;&#x529F;&#x80FD;&#x3002;</p><p>Lombok&#x4E3B;&#x8981;&#x5728;&#x7C7B;<code>LombokProcessor</code>&#x5904;&#x7406;&#x4E86;&#x81EA;&#x5DF1;&#x7684;&#x6CE8;&#x89E3;&#x901A;&#x8FC7;AST&#x751F;&#x6210;&#x4EE3;&#x7801;&#x3002;&#x5982;&#x4E0B;&#xFF0C;&#x4E3B;&#x8981;&#x770B;&#x4E24;&#x4E2A;&#x91CD;&#x5199;&#x65B9;&#x6CD5;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x521D;&#x59CB;&#x5316;&#x672C;&#x6B21;&#x5904;&#x7406;&#x7684;&#x4E00;&#x4E9B;&#x53D8;&#x91CF;&#x7B49;</span></span><br><span class="line"><span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">(ProcessingEnvironment procEnv)</span> </span>{</span><br><span class="line">  <span class="keyword">super</span>.init(procEnv);</span><br><span class="line">  <span class="comment">// &#x5224;&#x65AD;lombok&#x662F;&#x5426;&#x88AB;&#x7981;&#x7528;</span></span><br><span class="line">  <span class="keyword">if</span> (System.getProperty(<span class="string">&quot;lombok.disable&quot;</span>) != <span class="keyword">null</span>) {</span><br><span class="line">    lombokDisabled = <span class="keyword">true</span>;</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">this</span>.processingEnv = procEnv;</span><br><span class="line">  <span class="keyword">this</span>.javacProcessingEnv = getJavacProcessingEnvironment(procEnv);</span><br><span class="line">  <span class="keyword">this</span>.javacFiler = getJavacFiler(procEnv.getFiler());</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x66FF;&#x6362;&#x7C7B;&#x52A0;&#x8F7D;&#x5668;&#x3001;&#x5BF9;netbeans IDE&#x76F8;&#x5173;hook&#x5904;&#x7406;&#x3001;&#x66FF;&#x6362;JavaFileManager</span></span><br><span class="line">  placePostCompileAndDontMakeForceRoundDummiesHook();</span><br><span class="line">  trees = Trees.instance(javacProcessingEnv);</span><br><span class="line">  transformer = <span class="keyword">new</span> JavacTransformer(procEnv.getMessager(), trees);</span><br><span class="line">  <span class="comment">// &#x83B7;&#x53D6;&#x6807;&#x8BB0;HandlerPriority&#x6CE8;&#x89E3;&#x7684;&#x6240;&#x6709;&#x4F18;&#x5148;&#x7EA7;</span></span><br><span class="line">  SortedSet&lt;Long&gt; p = transformer.getPriorities();</span><br><span class="line">  <span class="keyword">if</span> (p.isEmpty()) {</span><br><span class="line">    <span class="keyword">this</span>.priorityLevels = <span class="keyword">new</span> <span class="keyword">long</span>[] {<span class="number">0L</span>};</span><br><span class="line">    <span class="keyword">this</span>.priorityLevelsRequiringResolutionReset = <span class="keyword">new</span> HashSet&lt;Long&gt;();</span><br><span class="line">  } <span class="keyword">else</span> {</span><br><span class="line">    <span class="keyword">this</span>.priorityLevels = <span class="keyword">new</span> <span class="keyword">long</span>[p.size()];</span><br><span class="line">    <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">// &#x5FAA;&#x73AF;&#x6240;&#x6709;&#x83B7;&#x53D6;&#x5230;&#x7684;&#x6CE8;&#x91CA;&#x6216;&#x8005;visit&#x5904;&#x7406;&#x4F18;&#x5148;&#x7EA7;</span></span><br><span class="line">    <span class="keyword">for</span> (Long prio : p) <span class="keyword">this</span>.priorityLevels[i++] = prio;</span><br><span class="line">    <span class="keyword">this</span>.priorityLevelsRequiringResolutionReset = transformer.getPrioritiesRequiringResolutionReset();</span><br><span class="line">  }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/** {<span class="doctag">@inheritDoc</span>} */</span></span><br><span class="line"><span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">process</span><span class="params">(Set&lt;? extends TypeElement&gt; annotations, RoundEnvironment roundEnv)</span> </span>{</span><br><span class="line">  <span class="comment">// &#x5982;&#x679C;&#x7981;&#x7528;&#xFF0C;&#x5219;&#x4E0D;&#x5904;&#x7406;lombok&#x6CE8;&#x89E3;</span></span><br><span class="line">  <span class="keyword">if</span> (lombokDisabled) <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">  <span class="comment">// &#x662F;&#x5426;&#x5DF2;&#x7ECF;&#x5904;&#x7406;&#x7ED3;&#x675F;</span></span><br><span class="line">  <span class="keyword">if</span> (roundEnv.processingOver()) {</span><br><span class="line">    cleanup.run();</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">  }</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// We have: A sorted set of all priority levels: &apos;priorityLevels&apos;</span></span><br><span class="line">  </span><br><span class="line">  <span class="comment">// Step 1: Take all CUs which aren&apos;t already in the map. Give them the first priority level.</span></span><br><span class="line">  </span><br><span class="line">  String randomModuleName = <span class="keyword">null</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// &#x6807;&#x8BB0;&#x6240;&#x6709;&#x7F16;&#x8BD1;&#x5355;&#x5143;&#x7684;&#x4F18;&#x5148;&#x7EA7;</span></span><br><span class="line">  <span class="comment">// &#x5982;&#x679C;&#x662F;&#x7B2C;&#x4E8C;&#x6B21;&#x5FAA;&#x73AF;&#xFF0C;&#x56E0;&#x4E3A;roots&#x5DF2;&#x7ECF;&#x5305;&#x542B;&#x4E86;&#x8FD9;&#x4E2A;&#x7F16;&#x8BD1;&#x5355;&#x5143;&#xFF0C;&#x6240;&#x4EE5;&#x4F1A;&#x5FFD;&#x7565;</span></span><br><span class="line">  <span class="keyword">for</span> (Element element : roundEnv.getRootElements()) {</span><br><span class="line">    <span class="keyword">if</span> (randomModuleName == <span class="keyword">null</span>) randomModuleName = getModuleNameFor(element);</span><br><span class="line">    JCCompilationUnit unit = toUnit(element);</span><br><span class="line">    <span class="keyword">if</span> (unit == <span class="keyword">null</span>) <span class="keyword">continue</span>;</span><br><span class="line">    <span class="keyword">if</span> (roots.containsKey(unit)) <span class="keyword">continue</span>;</span><br><span class="line">    roots.put(unit, priorityLevels[<span class="number">0</span>]);</span><br><span class="line">  }</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">while</span> (<span class="keyword">true</span>) {</span><br><span class="line">    <span class="comment">// Step 2: For all CUs (in the map, not the roundEnv!), run them across all handlers at their current prio level.</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// &#x5FAA;&#x73AF;&#x4F18;&#x5148;&#x7EA7;&#x5217;&#x8868;</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">long</span> prio : priorityLevels) {</span><br><span class="line">      List&lt;JCCompilationUnit&gt; cusForThisRound = <span class="keyword">new</span> ArrayList&lt;JCCompilationUnit&gt;();</span><br><span class="line">      <span class="comment">// &#x83B7;&#x53D6;&#x5728;&#x8BE5;&#x4F18;&#x5148;&#x7EA7;&#x4E0B;&#x7684;&#x6240;&#x6709;&#x7F16;&#x8BD1;&#x5355;&#x5143;&#x5E76;&#x52A0;&#x5165;&#x8BE5;&#x4F18;&#x5148;&#x7EA7;&#x4E0B;&#x9700;&#x8981;&#x5904;&#x7406;&#x7684;&#x7F16;&#x8BD1;&#x5355;&#x5143;&#x5217;&#x8868;&#x5185;</span></span><br><span class="line">      <span class="keyword">for</span> (Map.Entry&lt;JCCompilationUnit, Long&gt; entry : roots.entrySet()) {</span><br><span class="line">        Long prioOfCu = entry.getValue();</span><br><span class="line">        <span class="keyword">if</span> (prioOfCu == <span class="keyword">null</span> || prioOfCu != prio) <span class="keyword">continue</span>;</span><br><span class="line">        cusForThisRound.add(entry.getKey());</span><br><span class="line">      }</span><br><span class="line">      <span class="comment">// &#x6309;&#x7167;&#x4F18;&#x5148;&#x7EA7;&#x987A;&#x5E8F;&#x6267;&#x884C;&#x7F16;&#x8BD1;&#x5355;&#x5143;</span></span><br><span class="line">      <span class="comment">// &#x8BBF;&#x95EE;AST&#x6811;&#x5E76;&#x7F16;&#x8BD1;&#x76EE;&#x6807;&#x6CE8;&#x89E3;</span></span><br><span class="line">      transformer.transform(prio, javacProcessingEnv.getContext(), cusForThisRound, cleanup);</span><br><span class="line">    }</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// Step 3: Push up all CUs to the next level. Set level to null if there is no next level.</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// &#x6392;&#x9664;&#x6389;&#x5217;&#x8868;&#x7B2C;&#x4E00;&#x4E2A;&#x4F18;&#x5148;&#x7EA7;&#x51C6;&#x5907;&#x6267;&#x884C;&#x4E0B;&#x4E00;&#x6B21;&#x5FAA;&#x73AF;</span></span><br><span class="line">    Set&lt;Long&gt; newLevels = <span class="keyword">new</span> HashSet&lt;Long&gt;();</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = priorityLevels.length - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i--) {</span><br><span class="line">      Long curLevel = priorityLevels[i];</span><br><span class="line">      Long nextLevel = (i == priorityLevels.length - <span class="number">1</span>) ? <span class="keyword">null</span> : priorityLevels[i + <span class="number">1</span>];</span><br><span class="line">      List&lt;JCCompilationUnit&gt; cusToAdvance = <span class="keyword">new</span> ArrayList&lt;JCCompilationUnit&gt;();</span><br><span class="line">      <span class="keyword">for</span> (Map.Entry&lt;JCCompilationUnit, Long&gt; entry : roots.entrySet()) {</span><br><span class="line">        <span class="keyword">if</span> (curLevel.equals(entry.getValue())) {</span><br><span class="line">          cusToAdvance.add(entry.getKey());</span><br><span class="line">          newLevels.add(nextLevel);</span><br><span class="line">        }</span><br><span class="line">      }</span><br><span class="line">      <span class="keyword">for</span> (JCCompilationUnit unit : cusToAdvance) {</span><br><span class="line">        roots.put(unit, nextLevel);</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line">    newLevels.remove(<span class="keyword">null</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// Step 4: If ALL values are null, quit. Else, either do another loop right now or force a resolution reset by forcing a new round in the annotation processor.</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// &#x5224;&#x65AD;&#x662F;&#x5426;&#x5C06;&#x6240;&#x6709;&#x4F18;&#x5148;&#x7EA7;&#x6392;&#x9664;&#xFF0C;&#x4F18;&#x5148;&#x7EA7;&#x5217;&#x8868;&#x4E3A;&#x7A7A;&#xFF0C;&#x5219;&#x7ED3;&#x675F;</span></span><br><span class="line">    <span class="keyword">if</span> (newLevels.isEmpty()) <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    newLevels.retainAll(priorityLevelsRequiringResolutionReset);</span><br><span class="line">    <span class="keyword">if</span> (!newLevels.isEmpty()) {</span><br><span class="line">      <span class="comment">// Force a new round to reset resolution. The next round will cause this method (process) to be called again.</span></span><br><span class="line">      forceNewRound(randomModuleName, javacFiler);</span><br><span class="line">      <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    }</span><br><span class="line">    <span class="comment">// None of the new levels need resolution, so just keep going.</span></span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p><code>init</code>&#x65B9;&#x6CD5;&#x4E3B;&#x8981;&#x662F;&#x505A;&#x4E00;&#x4E9B;&#x521D;&#x59CB;&#x5316;&#xFF1B;</p><p><code>process</code>&#x65B9;&#x6CD5;&#x5185;&#x4E3B;&#x8981;&#x662F;&#x5C06;&#x6CE8;&#x89E3;&#x4EE5;&#x53CA;visitor&#x5904;&#x7406;&#x5668;&#x7684;&#x6309;&#x7167;&#x4F18;&#x5148;&#x7EA7;&#x5212;&#x5206;&#xFF0C;&#x7136;&#x540E;&#x6BCF;&#x6B21;&#x6267;&#x884C;&#x5B8C;&#x6210;&#x540E;&#xFF0C;&#x6392;&#x9664;&#x6700;&#x5F00;&#x59CB;&#x7684;&#x4E00;&#x4E2A;&#x4F18;&#x5148;&#x7EA7;&#x540E;&#xFF0C;&#x91CD;&#x65B0;&#x5F00;&#x59CB;&#x4E0B;&#x4E00;&#x8F6E;&#x7F16;&#x8BD1;&#x3002;&#x77E5;&#x9053;&#x6240;&#x6709;&#x4F18;&#x5148;&#x7EA7;&#x6392;&#x9664;&#x5B8C;&#x6BD5;&#x3002;&#x8FD9;&#x4E48;&#x505A;&#x7684;&#x539F;&#x56E0;&#xFF0C;&#x5E94;&#x8BE5;&#x662F;&#x4E3A;&#x4E86;&#x5728;&#x9AD8;&#x4F18;&#x5148;&#x7EA7;&#x5904;&#x7406;&#x5668;&#x5904;&#x7406;&#x5B8C;&#x6210;&#x751F;&#x6210;&#x6587;&#x4EF6;&#x540E;&#xFF0C;&#x80FD;&#x591F;&#x8BA9;&#x4F4E;&#x4F18;&#x5148;&#x7EA7;&#x5904;&#x7406;&#x5668;&#x6839;&#x636E;&#x9AD8;&#x4F18;&#x5148;&#x7EA7;&#x5904;&#x7406;&#x5668;&#x751F;&#x6210;&#x7684;&#x6587;&#x4EF6;&#x91CD;&#x65B0;&#x6267;&#x884C;&#x4E00;&#x904D;&#x9632;&#x6B62;&#x9057;&#x6F0F;&#x751F;&#x6210;&#x7684;&#x65B0;&#x7684;&#x4EE3;&#x7801;</p><h3 id="&#x603B;&#x7ED3;"><a href="#&#x603B;&#x7ED3;" class="headerlink" title="&#x603B;&#x7ED3;"></a>&#x603B;&#x7ED3;</h3><ul><li>&#x8BE6;&#x7EC6;&#x4E86;&#x89E3;&#x4E86;JSR269&#x5185;&#x90E8;&#x7684;&#x6267;&#x884C;&#x903B;&#x8F91;</li><li>&#x4E86;&#x89E3;&#x4E86;JAVAC&#x7684;&#x7F16;&#x8BD1;&#x8FC7;&#x7A0B;</li><li>&#x4E86;&#x89E3;&#x4E86;Lombok&#x5185;&#x90E8;&#x7684;&#x6267;&#x884C;&#x539F;&#x7406;&#xFF0C;&#x53EF;&#x4EE5;&#x4F9D;&#x6258;&#x73B0;&#x6709;Lombok&#x5904;&#x7406;&#x5668;&#xFF0C;&#x81EA;&#x5B9A;&#x4E49;&#x6CE8;&#x89E3;</li></ul><p>&#x603B;&#x4E4B;&#xFF0C;&#x6536;&#x83B7;&#x6EE1;&#x6EE1;&#x3002;</p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;一直在使用Lombok以及MapStruct，但是对于它们能够在编译阶段直接生成实例代码却没有仔细了解过。最近刚好在部门内做了一次分享，也在这里对具体原理做一个详细阐述。&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="JSR" scheme="https://xuqiang.me/categories/Java/JSR/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="jsr269" scheme="https://xuqiang.me/tags/jsr269/"/>
    
  </entry>
  
  <entry>
    <title>Validator内国际化未生效的解决</title>
    <link href="https://xuqiang.me/Validator%E5%86%85%E5%9B%BD%E9%99%85%E5%8C%96%E6%9C%AA%E7%94%9F%E6%95%88%E7%9A%84%E8%A7%A3%E5%86%B3.html"/>
    <id>https://xuqiang.me/Validator内国际化未生效的解决.html</id>
    <published>2019-02-20T15:58:58.000Z</published>
    <updated>2019-05-07T15:34:19.493Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x7B14;&#x8005;&#x5728;&#x6700;&#x8FD1;&#x5E94;&#x7528;&#x56FD;&#x9645;&#x5316;&#x6821;&#x9A8C;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x78B0;&#x5230;&#x4E00;&#x4E2A;&#x5947;&#x602A;&#x7684;&#x95EE;&#x9898;&#xFF1A;&#x56FD;&#x9645;&#x5316;&#x59CB;&#x7EC8;&#x4E0D;&#x80FD;&#x751F;&#x6548;&#xFF0C;&#x6D88;&#x606F;&#x8FD4;&#x56DE;&#x7684;&#x4ECD;&#x65E7;&#x662F;&#x6A21;&#x677F;&#x6D88;&#x606F;&#x3002;</p><a id="more"></a><h3 id="&#x76F8;&#x5173;&#x6E90;&#x7801;"><a href="#&#x76F8;&#x5173;&#x6E90;&#x7801;" class="headerlink" title="&#x76F8;&#x5173;&#x6E90;&#x7801;"></a>&#x76F8;&#x5173;&#x6E90;&#x7801;</h3><p><code>Java Bean</code>:<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DemoParam</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="meta">@NotNull</span>(message = <span class="string">&quot;{validator.demo.name.not-null}&quot;</span>)</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@NotNull</span>(</span><br><span class="line">        groups = DemoParamValidateGroup1.class,</span><br><span class="line">        message = <span class="string">&quot;{validator.demo.title.not-blank}&quot;</span></span><br><span class="line">    )</span><br><span class="line">    <span class="meta">@NotEmpty</span>(</span><br><span class="line">        groups = DemoParamValidateGroup1.class,</span><br><span class="line">        message = <span class="string">&quot;{validator.demo.title.not-blank}&quot;</span></span><br><span class="line">    )</span><br><span class="line">    <span class="meta">@Length</span>(</span><br><span class="line">        min = <span class="number">1</span>,</span><br><span class="line">        max = <span class="number">64</span>,</span><br><span class="line">        groups = DemoParamValidateGroup1.class,</span><br><span class="line">        message = <span class="string">&quot;{validator.demo.title.illegal-length-1-64}&quot;</span></span><br><span class="line">    )</span><br><span class="line">    <span class="keyword">private</span> String title;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * first validation group</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">DemoParamValidateGroup1</span> </span>{}</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p><code>DemoApi</code>:<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@PostMapping</span>(<span class="string">&quot;/param1&quot;</span>)</span><br><span class="line"><span class="function"><span class="keyword">public</span> Object <span class="title">param1</span><span class="params">(@Validated @RequestBody DemoParam demoParam)</span> </span>{</span><br><span class="line">    <span class="keyword">return</span> Result.getSuccResult(demoParam);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p><code>ValidatorConfig</code>:<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ValidatorConfig</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> MessageSource messageSource;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">ValidatorConfig</span><span class="params">(MessageSource messageSource)</span> </span>{</span><br><span class="line">        <span class="keyword">this</span>.messageSource = messageSource;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Validator <span class="title">validator</span><span class="params">()</span> </span>{</span><br><span class="line">        LocalValidatorFactoryBean validator = <span class="keyword">new</span> LocalValidatorFactoryBean();</span><br><span class="line">        validator.setValidationMessageSource(messageSource);</span><br><span class="line">        <span class="keyword">return</span> validator;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p><code>DemoApiTest</code>:<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test_param1_default</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>{</span><br><span class="line">    DemoParam demoParam = <span class="keyword">new</span> DemoParam();</span><br><span class="line"></span><br><span class="line">    mockMvc.perform(</span><br><span class="line">        post(<span class="string">&quot;/api/demo/param1&quot;</span>)</span><br><span class="line">            .contentType(MediaType.APPLICATION_JSON_UTF8)</span><br><span class="line">            .content(JSON.toJSONString(demoParam)))</span><br><span class="line">        .andExpect(status().isOk())</span><br><span class="line">        .andExpect(jsonPath(<span class="string">&quot;$.code&quot;</span>, is(DemoResultCode.BAD_REQUEST.getCode())));</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><h3 id="&#x5B9A;&#x4F4D;&#x95EE;&#x9898;"><a href="#&#x5B9A;&#x4F4D;&#x95EE;&#x9898;" class="headerlink" title="&#x5B9A;&#x4F4D;&#x95EE;&#x9898;"></a>&#x5B9A;&#x4F4D;&#x95EE;&#x9898;</h3><p>&#x7531;&#x4E8E;&#x7B14;&#x8005;&#x5E76;&#x6CA1;&#x6709;&#x5728;&#x4EE5;&#x524D;&#x770B;&#x8FC7;<code>spring</code>&#x7684;<code>validator</code>&#x6E90;&#x7801;&#xFF1B;&#x6240;&#x4EE5;&#xFF0C;&#x6253;&#x7B97;&#x4ECE;&#x6821;&#x9A8C;&#x7684;&#x6267;&#x884C;&#x5165;&#x53E3;&#x5904;&#x5165;&#x624B;&#x3002;</p><p>&#x8BF7;&#x6C42;&#x662F;<code>POST</code>&#x5F62;&#x5F0F;&#xFF0C;&#x800C;&#x5728;&#x7C7B;<code>RequestResponseBodyMethodProcessor</code>&#x7684;<code>resolveArgument</code>&#x65B9;&#x6CD5;&#x5185;&#xFF0C;&#x4F1A;&#x5BF9;&#x6CE8;&#x89E3;&#x6709;<code>@RequestBody</code>&#x7684;&#x53C2;&#x6570;&#x505A;&#x53C2;&#x6570;&#x89E3;&#x6790;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> Object <span class="title">resolveArgument</span><span class="params">(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,</span></span></span><br><span class="line"><span class="function"><span class="params">    NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory)</span> <span class="keyword">throws</span> Exception </span>{</span><br><span class="line"></span><br><span class="line">  parameter = parameter.nestedIfOptional();</span><br><span class="line">  Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());&#x2460;</span><br><span class="line">  String name = Conventions.getVariableNameForParameter(parameter);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (binderFactory != <span class="keyword">null</span>) {</span><br><span class="line">    WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);</span><br><span class="line">    <span class="keyword">if</span> (arg != <span class="keyword">null</span>) {</span><br><span class="line">      validateIfApplicable(binder, parameter);</span><br><span class="line">      <span class="keyword">if</span> (binder.getBindingResult().hasErrors() &amp;&amp; isBindExceptionRequired(binder, parameter)) { &#x2461;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> MethodArgumentNotValidException(parameter, binder.getBindingResult());</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">if</span> (mavContainer != <span class="keyword">null</span>) {</span><br><span class="line">      mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> adaptArgumentIfNecessary(arg, parameter);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728;&#x4E0A;&#x8FF0;&#x7684;&#x89E3;&#x6790;&#x5757;&#x5185;&#xFF0C;&#x2460; &#x5904;&#x7684;&#x4EE3;&#x7801;&#x662F;&#x4F7F;&#x7528;<code>MessageHttpConverters</code>&#x5C06;<code>json</code>&#x5B57;&#x7B26;&#x4E32;&#x8F6C;&#x5316;&#x4E3A;&#x76EE;&#x6807;&#x5B9E;&#x4F8B;&#xFF1B;&#x2461; &#x5904;&#x7684;&#x4EE3;&#x7801;&#x901A;&#x8FC7;&#x521B;&#x5EFA;&#x7684;<code>WebDataBinder</code>&#x83B7;&#x53D6;&#x6821;&#x9A8C;&#x540E;&#x7684;&#x7ED3;&#x679C;&#xFF0C;&#x901A;&#x8FC7;&#x7ED3;&#x679C;&#x5224;&#x65AD;&#x662F;&#x5426;&#x6821;&#x9A8C;&#x901A;&#x8FC7;&#x3002;&#x800C;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x7684;&#x9519;&#x8BEF;&#x4FE1;&#x606F;&#x6784;&#x5EFA;&#x80AF;&#x5B9A;&#x5728;<code>validateIfApplicable(binder, parameter);</code>&#x8BED;&#x53E5;&#x5185;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">validateIfApplicable</span><span class="params">(WebDataBinder binder, MethodParameter parameter)</span> </span>{</span><br><span class="line">  Annotation[] annotations = parameter.getParameterAnnotations();</span><br><span class="line">  <span class="keyword">for</span> (Annotation ann : annotations) {</span><br><span class="line">    Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);</span><br><span class="line">    <span class="keyword">if</span> (validatedAnn != <span class="keyword">null</span> || ann.annotationType().getSimpleName().startsWith(<span class="string">&quot;Valid&quot;</span>)) { &#x2462;</span><br><span class="line">      Object hints = (validatedAnn != <span class="keyword">null</span> ? validatedAnn.value() : AnnotationUtils.getValue(ann));</span><br><span class="line">      Object[] validationHints = (hints <span class="keyword">instanceof</span> Object[] ? (Object[]) hints : <span class="keyword">new</span> Object[] {hints});</span><br><span class="line">      binder.validate(validationHints); &#x2463;</span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x2462; &#x5904;&#x5728;&#x6821;&#x9A8C;&#x53C2;&#x6570;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x4F1A;&#x6821;&#x9A8C;&#x53C2;&#x6570;&#x7684;&#x6CE8;&#x89E3;&#x662F;&#x5426;&#x6709;&#x6CE8;&#x89E3;&#xFF0C;&#x5982;&#x679C;&#x6CE8;&#x89E3;&#x4E3A;<code>@Validated</code>&#x6216;&#x8005;&#x6CE8;&#x89E3;&#x4EE5;<code>Valid</code>&#x5F00;&#x5934;&#xFF0C;&#x5219;&#x6821;&#x9A8C;&#x8BE5;&#x53C2;&#x6570;&#xFF0C;&#x5982; &#x2463; &#x5904;&#x7684;&#x4EE3;&#x7801;&#xFF1B;<code>binder</code>&#x662F;&#x7C7B;<code>DataBinder</code>&#x7684;&#x5B9E;&#x4F8B;&#xFF0C;&#x6821;&#x9A8C;&#x7684;&#x903B;&#x8F91;&#x5982;&#x4E0B;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">validate</span><span class="params">(Object... validationHints)</span> </span>{</span><br><span class="line">  Object target = getTarget();</span><br><span class="line">  Assert.state(target != <span class="keyword">null</span>, <span class="string">&quot;No target to validate&quot;</span>);</span><br><span class="line">  BindingResult bindingResult = getBindingResult(); &#x2464;</span><br><span class="line">  <span class="comment">// Call each validator with the same binding result</span></span><br><span class="line">  <span class="keyword">for</span> (Validator validator : getValidators()) {</span><br><span class="line">    <span class="keyword">if</span> (!ObjectUtils.isEmpty(validationHints) &amp;&amp; validator <span class="keyword">instanceof</span> SmartValidator) {</span><br><span class="line">      ((SmartValidator) validator).validate(target, bindingResult, validationHints); &#x2465;</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (validator != <span class="keyword">null</span>) {</span><br><span class="line">      validator.validate(target, bindingResult); &#x2465;</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x2464; &#x5904;&#x4EE3;&#x7801;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x9ED8;&#x8BA4;&#x7684;&#x6821;&#x9A8C;&#x7ED3;&#x679C;&#xFF0C;&#x7136;&#x540E;&#x4F20;&#x9012;&#x8FDB;&#x5165;&#x5B9E;&#x9645;&#x7684;&#x6821;&#x9A8C;&#x65B9;&#x6CD5; &#x2465; &#x5185;&#x3002;&#x5728;<code>Spring Boot</code>&#x6846;&#x67B6;&#x5185;&#xFF0C;&#x6821;&#x9A8C;&#x6846;&#x67B6;&#x7684;&#x5B9E;&#x73B0;&#x4EA4;&#x7531;<code>Hibernate Validator</code>&#x5B9E;&#x73B0;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> &lt;T&gt; Set&lt;ConstraintViolation&lt;T&gt;&gt; validate(T object, Class&lt;?&gt;... groups) {</span><br><span class="line">  Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );</span><br><span class="line">  sanityCheckGroups( groups );</span><br><span class="line"></span><br><span class="line">  ValidationContext&lt;T&gt; validationContext = getValidationContextBuilder().forValidate( object );</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> ( !validationContext.getRootBeanMetaData().hasConstraints() ) {</span><br><span class="line">    <span class="keyword">return</span> Collections.emptySet();</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  ValidationOrder validationOrder = determineGroupValidationOrder( groups );</span><br><span class="line">  ValueContext&lt;?, Object&gt; valueContext = ValueContext.getLocalExecutionContext(</span><br><span class="line">      validatorScopedContext.getParameterNameProvider(),</span><br><span class="line">      object,</span><br><span class="line">      validationContext.getRootBeanMetaData(),</span><br><span class="line">      PathImpl.createRootPath()</span><br><span class="line">  );</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> validateInContext( validationContext, valueContext, validationOrder ); &#x2466;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728; &#x2466; &#x5904;&#xFF0C;&#x901A;&#x8FC7;&#x6821;&#x9A8C;&#x548C;&#x503C;&#x7684;&#x4E0A;&#x4E0B;&#x6587;&#x6821;&#x9A8C;&#x5177;&#x4F53;&#x7684;&#x5185;&#x5BB9;&#xFF1B;&#x4E4B;&#x540E;&#x5728;<code>ConstraintTree</code>&#x7C7B;&#x5185;&#x505A;&#x5177;&#x4F53;&#x7684;&#x6821;&#x9A8C;&#xFF0C;&#x5176;&#x4E2D;&#x7684;&#x5C42;&#x6B21;&#x8C03;&#x7528;&#x5C31;&#x4E0D;&#x5728;&#x672C;&#x7BC7;&#x5185;&#x63CF;&#x8FF0;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> <span class="keyword">final</span> &lt;T, V&gt; Set&lt;ConstraintViolation&lt;T&gt;&gt; validateSingleConstraint(ValidationContext&lt;T&gt; executionContext,</span><br><span class="line">ValueContext&lt;?, ?&gt; valueContext,</span><br><span class="line">ConstraintValidatorContextImpl constraintValidatorContext,</span><br><span class="line">ConstraintValidator&lt;A, V&gt; validator) {</span><br><span class="line">  <span class="keyword">boolean</span> isValid;</span><br><span class="line">  <span class="keyword">try</span> {</span><br><span class="line">    <span class="meta">@SuppressWarnings</span>(<span class="string">&quot;unchecked&quot;</span>)</span><br><span class="line">    V validatedValue = (V) valueContext.getCurrentValidatedValue();</span><br><span class="line">    isValid = validator.isValid( validatedValue, constraintValidatorContext );</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">catch</span> (RuntimeException e) {</span><br><span class="line">    <span class="keyword">if</span> ( e <span class="keyword">instanceof</span> ConstraintDeclarationException ) {</span><br><span class="line">      <span class="keyword">throw</span> e;</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">throw</span> LOG.getExceptionDuringIsValidCallException( e );</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">if</span> ( !isValid ) {</span><br><span class="line">    <span class="comment">//We do not add these violations yet, since we don&apos;t know how they are</span></span><br><span class="line">    <span class="comment">//going to influence the final boolean evaluation</span></span><br><span class="line">    <span class="keyword">return</span> executionContext.createConstraintViolations( &#x2467;</span><br><span class="line">        valueContext, constraintValidatorContext</span><br><span class="line">    );</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">return</span> Collections.emptySet();</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728; &#x2467; &#x5904;&#xFF0C;&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x5728;&#x8FD9;&#x91CC;&#x521B;&#x5EFA;&#x9519;&#x8BEF;&#x4FE1;&#x606F;&#x7684;&#x5B9E;&#x4F8B;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> ConstraintViolation&lt;T&gt; <span class="title">createConstraintViolation</span><span class="params">(ValueContext&lt;?, ?&gt; localContext, ConstraintViolationCreationContext constraintViolationCreationContext, ConstraintDescriptor&lt;?&gt; descriptor)</span> </span>{</span><br><span class="line">  String messageTemplate = constraintViolationCreationContext.getMessage(); &#x2468;</span><br><span class="line">  String interpolatedMessage = interpolate( &#x2469;</span><br><span class="line">      messageTemplate,</span><br><span class="line">      localContext.getCurrentValidatedValue(),</span><br><span class="line">      descriptor,</span><br><span class="line">      constraintViolationCreationContext.getMessageParameters(),</span><br><span class="line">      constraintViolationCreationContext.getExpressionVariables()</span><br><span class="line">  );</span><br><span class="line">  <span class="comment">// at this point we make a copy of the path to avoid side effects</span></span><br><span class="line">  Path path = PathImpl.createCopy( constraintViolationCreationContext.getPath() );</span><br><span class="line">  Object dynamicPayload = constraintViolationCreationContext.getDynamicPayload();</span><br><span class="line"></span><br><span class="line">  <span class="keyword">switch</span> ( validationOperation ) {</span><br><span class="line">    <span class="keyword">case</span> PARAMETER_VALIDATION:</span><br><span class="line">      <span class="keyword">return</span> ConstraintViolationImpl.forParameterValidation(</span><br><span class="line">          messageTemplate,</span><br><span class="line">          constraintViolationCreationContext.getMessageParameters(),</span><br><span class="line">          constraintViolationCreationContext.getExpressionVariables(),</span><br><span class="line">          interpolatedMessage,</span><br><span class="line">          getRootBeanClass(),</span><br><span class="line">          getRootBean(),</span><br><span class="line">          localContext.getCurrentBean(),</span><br><span class="line">          localContext.getCurrentValidatedValue(),</span><br><span class="line">          path,</span><br><span class="line">          descriptor,</span><br><span class="line">          localContext.getElementType(),</span><br><span class="line">          executableParameters,</span><br><span class="line">          dynamicPayload</span><br><span class="line">      );</span><br><span class="line">    <span class="keyword">case</span> RETURN_VALUE_VALIDATION:</span><br><span class="line">      <span class="keyword">return</span> ConstraintViolationImpl.forReturnValueValidation(</span><br><span class="line">          messageTemplate,</span><br><span class="line">          constraintViolationCreationContext.getMessageParameters(),</span><br><span class="line">          constraintViolationCreationContext.getExpressionVariables(),</span><br><span class="line">          interpolatedMessage,</span><br><span class="line">          getRootBeanClass(),</span><br><span class="line">          getRootBean(),</span><br><span class="line">          localContext.getCurrentBean(),</span><br><span class="line">          localContext.getCurrentValidatedValue(),</span><br><span class="line">          path,</span><br><span class="line">          descriptor,</span><br><span class="line">          localContext.getElementType(),</span><br><span class="line">          executableReturnValue,</span><br><span class="line">          dynamicPayload</span><br><span class="line">      );</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">      <span class="keyword">return</span> ConstraintViolationImpl.forBeanValidation(</span><br><span class="line">          messageTemplate,</span><br><span class="line">          constraintViolationCreationContext.getMessageParameters(),</span><br><span class="line">          constraintViolationCreationContext.getExpressionVariables(),</span><br><span class="line">          interpolatedMessage,</span><br><span class="line">          getRootBeanClass(),</span><br><span class="line">          getRootBean(),</span><br><span class="line">          localContext.getCurrentBean(),</span><br><span class="line">          localContext.getCurrentValidatedValue(),</span><br><span class="line">          path,</span><br><span class="line">          descriptor,</span><br><span class="line">          localContext.getElementType(),</span><br><span class="line">          dynamicPayload</span><br><span class="line">      );</span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728; &#x2468; &#x5904;&#xFF0C;&#x83B7;&#x53D6;&#x539F;&#x6D88;&#x606F;&#x7684;&#x6D88;&#x606F;&#x6A21;&#x677F;&#xFF0C;&#x5373;&#xFF1A;<code>{validator.demo.name.not-null}</code>&#xFF0C;&#x4E4B;&#x540E;&#x901A;&#x8FC7;<code>interpolate</code>&#x65B9;&#x6CD5;&#xFF0C;&#x5C06;&#x6A21;&#x677F;&#x6D88;&#x606F;&#x66FF;&#x6362;&#x4E3A;&#x89E3;&#x6790;&#x540E;&#x7684;&#x5B57;&#x7B26;&#x4E32;&#x3002;</p><p>&#x4E00;&#x5C42;&#x5C42;&#x9012;&#x5F52;&#xFF1A;<code>ValidationContext::interpolate -&gt; AbstractMessageInterpolator::interpolate -&gt; AbstractMessageInterpolator::interpolateMessage</code>&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> String <span class="title">interpolateMessage</span><span class="params">(String message, Context context, Locale locale)</span> <span class="keyword">throws</span> MessageDescriptorFormatException </span>{</span><br><span class="line">  <span class="comment">// if the message does not contain any message parameter, we can ignore the next steps and just return</span></span><br><span class="line">  <span class="comment">// the unescaped message. It avoids storing the message in the cache and a cache lookup.</span></span><br><span class="line">  <span class="keyword">if</span> ( message.indexOf( <span class="string">&apos;{&apos;</span> ) &lt; <span class="number">0</span> ) {</span><br><span class="line">    <span class="keyword">return</span> replaceEscapedLiterals( message );</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  String resolvedMessage = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// either retrieve message from cache, or if message is not yet there or caching is disabled,</span></span><br><span class="line">  <span class="comment">// perform message resolution algorithm (step 1)</span></span><br><span class="line">  <span class="keyword">if</span> ( cachingEnabled ) {</span><br><span class="line">    resolvedMessage = resolvedMessages.computeIfAbsent( <span class="keyword">new</span> LocalizedMessage( message, locale ), lm -&gt; resolveMessage( message, locale ) );</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">else</span> {</span><br><span class="line">    resolvedMessage = resolveMessage( message, locale ); </span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="comment">// there&apos;s no need for steps 2-3 unless there&apos;s `{param}`/`${expr}` in the message</span></span><br><span class="line">  <span class="keyword">if</span> ( resolvedMessage.indexOf( <span class="string">&apos;{&apos;</span> ) &gt; -<span class="number">1</span> ) {</span><br><span class="line">    <span class="comment">// resolve parameter expressions (step 2)</span></span><br><span class="line">    resolvedMessage = interpolateExpression(</span><br><span class="line">        <span class="keyword">new</span> TokenIterator( getParameterTokens( resolvedMessage, tokenizedParameterMessages, InterpolationTermType.PARAMETER ) ),</span><br><span class="line">        context,</span><br><span class="line">        locale</span><br><span class="line">    );</span><br><span class="line"></span><br><span class="line">    <span class="comment">// resolve EL expressions (step 3)</span></span><br><span class="line">    resolvedMessage = interpolateExpression(</span><br><span class="line">        <span class="keyword">new</span> TokenIterator( getParameterTokens( resolvedMessage, tokenizedELMessages, InterpolationTermType.EL ) ),</span><br><span class="line">        context,</span><br><span class="line">        locale</span><br><span class="line">    );</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="comment">// last but not least we have to take care of escaped literals</span></span><br><span class="line">  resolvedMessage = replaceEscapedLiterals( resolvedMessage );</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> resolvedMessage;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x901A;&#x8FC7; <code>resolveMessage( message, locale )</code> &#x65B9;&#x6CD5;&#xFF0C;&#x4F1A;&#x771F;&#x6B63;&#x5C06;&#x6D88;&#x606F;&#x8F6C;&#x5316;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> String <span class="title">resolveMessage</span><span class="params">(String message, Locale locale)</span> </span>{</span><br><span class="line">  String resolvedMessage = message;</span><br><span class="line"></span><br><span class="line">  ResourceBundle userResourceBundle = userResourceBundleLocator</span><br><span class="line">      .getResourceBundle( locale );</span><br><span class="line"></span><br><span class="line">  ResourceBundle constraintContributorResourceBundle = contributorResourceBundleLocator</span><br><span class="line">      .getResourceBundle( locale );</span><br><span class="line"></span><br><span class="line">  ResourceBundle defaultResourceBundle = defaultResourceBundleLocator</span><br><span class="line">      .getResourceBundle( locale );</span><br><span class="line"></span><br><span class="line">  String userBundleResolvedMessage;</span><br><span class="line">  <span class="keyword">boolean</span> evaluatedDefaultBundleOnce = <span class="keyword">false</span>;</span><br><span class="line">  <span class="keyword">do</span> {</span><br><span class="line">    <span class="comment">// search the user bundle recursive (step 1.1)</span></span><br><span class="line">    userBundleResolvedMessage = interpolateBundleMessage(</span><br><span class="line">        resolvedMessage, userResourceBundle, locale, <span class="keyword">true</span></span><br><span class="line">    );</span><br><span class="line"></span><br><span class="line">    <span class="comment">// search the constraint contributor bundle recursive (only if the user did not define a message)</span></span><br><span class="line">    <span class="keyword">if</span> ( !hasReplacementTakenPlace( userBundleResolvedMessage, resolvedMessage ) ) {</span><br><span class="line">      userBundleResolvedMessage = interpolateBundleMessage(</span><br><span class="line">          resolvedMessage, constraintContributorResourceBundle, locale, <span class="keyword">true</span></span><br><span class="line">      );</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// exit condition - we have at least tried to validate against the default bundle and there was no</span></span><br><span class="line">    <span class="comment">// further replacements</span></span><br><span class="line">    <span class="keyword">if</span> ( evaluatedDefaultBundleOnce &amp;&amp; !hasReplacementTakenPlace( userBundleResolvedMessage, resolvedMessage ) ) {</span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// search the default bundle non recursive (step 1.2)</span></span><br><span class="line">    resolvedMessage = interpolateBundleMessage(</span><br><span class="line">        userBundleResolvedMessage,</span><br><span class="line">        defaultResourceBundle,</span><br><span class="line">        locale,</span><br><span class="line">        <span class="keyword">false</span></span><br><span class="line">    );</span><br><span class="line">    evaluatedDefaultBundleOnce = <span class="keyword">true</span>;</span><br><span class="line">  } <span class="keyword">while</span> ( <span class="keyword">true</span> );</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> resolvedMessage;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5728; <code>ResourceBundle userResourceBundle = userResourceBundleLocator.getResourceBundle( locale );</code> &#x83B7;&#x53D6;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x5E76;&#x6CA1;&#x6709;&#x83B7;&#x53D6;&#x5230;<code>messages</code>&#x7684;<code>bundle</code>&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x8BF4;&#xFF0C;&#x4E0A;&#x6587;&#x8BBE;&#x7F6E;<code>validator.setValidationMessageSource(messageSource);</code>&#x5E76;&#x6CA1;&#x6709;&#x751F;&#x6548;&#x3002;</p><h3 id="&#x89E3;&#x6790;&#x95EE;&#x9898;"><a href="#&#x89E3;&#x6790;&#x95EE;&#x9898;" class="headerlink" title="&#x89E3;&#x6790;&#x95EE;&#x9898;"></a>&#x89E3;&#x6790;&#x95EE;&#x9898;</h3><p>&#x4E0A;&#x6587;&#xFF0C;&#x7B14;&#x8005;&#x901A;&#x8FC7;&#x4E00;&#x6B65;&#x6B65;&#x5B9A;&#x4F4D;&#x4E86;&#x89E3;&#x5230;&#xFF1A;<code>validator</code>&#x8BBE;&#x7F6E;&#x7684;<code>messageSource</code>&#x5E76;&#x6CA1;&#x6709;&#x751F;&#x6548;&#x3002;&#x90A3;&#x4E48;&#x63A5;&#x4E0B;&#x6765;&#xFF0C;&#x5C31;&#x9700;&#x8981;&#x63A2;&#x67E5;&#x4E0B;&#x8FD9;&#x4E2A;&#x5931;&#x6548;&#x7684;&#x539F;&#x56E0;&#x3002;</p><h4 id="ValidatorConfig&#x5185;&#x7684;Validator&#x672A;&#x6267;&#x884C;&#xFF1F;"><a href="#ValidatorConfig&#x5185;&#x7684;Validator&#x672A;&#x6267;&#x884C;&#xFF1F;" class="headerlink" title="ValidatorConfig&#x5185;&#x7684;Validator&#x672A;&#x6267;&#x884C;&#xFF1F;"></a><code>ValidatorConfig</code>&#x5185;&#x7684;<code>Validator</code>&#x672A;&#x6267;&#x884C;&#xFF1F;</h4><p>&#x5728;&#x7B14;&#x8005;&#x81EA;&#x5B9A;&#x4E49;&#x7684;<code>Validator</code>&#x6CE8;&#x5165;Bean&#x7684;&#x65B9;&#x6CD5;&#x5185;&#x589E;&#x52A0;&#x4E00;&#x4E2A;&#x65AD;&#x70B9;&#x3002;&#x7136;&#x540E;&#x91CD;&#x65B0;&#x542F;&#x52A8;&#x5E94;&#x7528;&#xFF0C;&#x5E94;&#x7528;&#x521D;&#x59CB;&#x5316;&#x8FC7;&#x7A0B;&#x987A;&#x5229;&#x5728;&#x65AD;&#x70B9;&#x5904;&#x505C;&#x7559;&#x3002;&#x90A3;&#x4E48;&#xFF0C;&#x672A;&#x6267;&#x884C;&#x7684;&#x5224;&#x65AD;&#x53EF;&#x4EE5;pass&#x3002;</p><h4 id="LocalValidatorFactoryBean&#x7684;&#x521D;&#x59CB;&#x5316;&#x8FC7;&#x7A0B;&#x672A;&#x6210;&#x529F;&#x8BBE;&#x7F6E;&#x56FD;&#x9645;&#x5316;&#xFF1F;"><a href="#LocalValidatorFactoryBean&#x7684;&#x521D;&#x59CB;&#x5316;&#x8FC7;&#x7A0B;&#x672A;&#x6210;&#x529F;&#x8BBE;&#x7F6E;&#x56FD;&#x9645;&#x5316;&#xFF1F;" class="headerlink" title="LocalValidatorFactoryBean&#x7684;&#x521D;&#x59CB;&#x5316;&#x8FC7;&#x7A0B;&#x672A;&#x6210;&#x529F;&#x8BBE;&#x7F6E;&#x56FD;&#x9645;&#x5316;&#xFF1F;"></a><code>LocalValidatorFactoryBean</code>&#x7684;&#x521D;&#x59CB;&#x5316;&#x8FC7;&#x7A0B;&#x672A;&#x6210;&#x529F;&#x8BBE;&#x7F6E;&#x56FD;&#x9645;&#x5316;&#xFF1F;</h4><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterPropertiesSet</span><span class="params">()</span> </span>{</span><br><span class="line">  Configuration&lt;?&gt; configuration;</span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">this</span>.providerClass != <span class="keyword">null</span>) {</span><br><span class="line">    ProviderSpecificBootstrap bootstrap = Validation.byProvider(<span class="keyword">this</span>.providerClass);</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">this</span>.validationProviderResolver != <span class="keyword">null</span>) {</span><br><span class="line">      bootstrap = bootstrap.providerResolver(<span class="keyword">this</span>.validationProviderResolver);</span><br><span class="line">    }</span><br><span class="line">    configuration = bootstrap.configure();</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">else</span> {</span><br><span class="line">    GenericBootstrap bootstrap = Validation.byDefaultProvider();</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">this</span>.validationProviderResolver != <span class="keyword">null</span>) {</span><br><span class="line">      bootstrap = bootstrap.providerResolver(<span class="keyword">this</span>.validationProviderResolver);</span><br><span class="line">    }</span><br><span class="line">    configuration = bootstrap.configure();</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Try Hibernate Validator 5.2&apos;s externalClassLoader(ClassLoader) method</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">this</span>.applicationContext != <span class="keyword">null</span>) {</span><br><span class="line">    <span class="keyword">try</span> {</span><br><span class="line">      Method eclMethod = configuration.getClass().getMethod(<span class="string">&quot;externalClassLoader&quot;</span>, ClassLoader.class);</span><br><span class="line">      ReflectionUtils.invokeMethod(eclMethod, configuration, <span class="keyword">this</span>.applicationContext.getClassLoader());</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">catch</span> (NoSuchMethodException ex) {</span><br><span class="line">      <span class="comment">// Ignore - no Hibernate Validator 5.2+ or similar provider</span></span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  MessageInterpolator targetInterpolator = <span class="keyword">this</span>.messageInterpolator; &#x2460;</span><br><span class="line">  <span class="keyword">if</span> (targetInterpolator == <span class="keyword">null</span>) {</span><br><span class="line">    targetInterpolator = configuration.getDefaultMessageInterpolator();</span><br><span class="line">  }</span><br><span class="line">  configuration.messageInterpolator(<span class="keyword">new</span> LocaleContextMessageInterpolator(targetInterpolator)); &#x2461;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">this</span>.traversableResolver != <span class="keyword">null</span>) {</span><br><span class="line">    configuration.traversableResolver(<span class="keyword">this</span>.traversableResolver);</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  ConstraintValidatorFactory targetConstraintValidatorFactory = <span class="keyword">this</span>.constraintValidatorFactory;</span><br><span class="line">  <span class="keyword">if</span> (targetConstraintValidatorFactory == <span class="keyword">null</span> &amp;&amp; <span class="keyword">this</span>.applicationContext != <span class="keyword">null</span>) {</span><br><span class="line">    targetConstraintValidatorFactory =</span><br><span class="line">        <span class="keyword">new</span> SpringConstraintValidatorFactory(<span class="keyword">this</span>.applicationContext.getAutowireCapableBeanFactory());</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">if</span> (targetConstraintValidatorFactory != <span class="keyword">null</span>) {</span><br><span class="line">    configuration.constraintValidatorFactory(targetConstraintValidatorFactory);</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">this</span>.parameterNameDiscoverer != <span class="keyword">null</span>) {</span><br><span class="line">    configureParameterNameProvider(<span class="keyword">this</span>.parameterNameDiscoverer, configuration);</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">this</span>.mappingLocations != <span class="keyword">null</span>) {</span><br><span class="line">    <span class="keyword">for</span> (Resource location : <span class="keyword">this</span>.mappingLocations) {</span><br><span class="line">      <span class="keyword">try</span> {</span><br><span class="line">        configuration.addMapping(location.getInputStream());</span><br><span class="line">      }</span><br><span class="line">      <span class="keyword">catch</span> (IOException ex) {</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException(<span class="string">&quot;Cannot read mapping resource: &quot;</span> + location);</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">this</span>.validationPropertyMap.forEach(configuration::addProperty);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Allow for custom post-processing before we actually build the ValidatorFactory.</span></span><br><span class="line">  postProcessConfiguration(configuration);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">this</span>.validatorFactory = configuration.buildValidatorFactory(); &#x2462;</span><br><span class="line">  setTargetValidator(<span class="keyword">this</span>.validatorFactory.getValidator());</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x89E3;&#x91CA;&#x4E0B;&#x56FD;&#x9645;&#x5316;&#x6D88;&#x606F;&#x5982;&#x4F55;&#x8BBE;&#x7F6E;&#x5230;<code>validator</code>&#x5DE5;&#x5382;&#x7684;&#x903B;&#x8F91;&#xFF1A;<br>&#x5728; &#x2460; &#x5904;&#x5C06;&#x56FD;&#x9645;&#x5316;&#x6D88;&#x606F;&#x89E3;&#x6790;&#x62E6;&#x622A;&#x5668;&#x8D4B;&#x503C;&#x7ED9;&#x4E86; <code>targetInterpolator</code> &#x53D8;&#x91CF;&#xFF1B;&#x800C;&#x8FD9;&#x4E2A;&#x53D8;&#x91CF;&#x6700;&#x7EC8;&#x4F20;&#x9012;&#x7ED9;&#x4E86;<code>configuration</code>&#xFF0C;&#x5982; &#x2462; &#x5904;&#x3002;&#x6700;&#x540E;&#xFF0C;&#x5728; &#x2462; &#x5904;&#x4F7F;&#x7528;<code>configuration</code>&#x7684;<code>buildValidatorFactory</code>&#x65B9;&#x6CD5;&#x6784;&#x5EFA;<code>validator</code>&#x7684;&#x5DE5;&#x5382;&#x3002;</p><p>&#x7B14;&#x8005;&#x5728;<code>validator</code>&#x7684;&#x5DE5;&#x5382;&#x7C7B;<code>LocalValidatorFactoryBean</code>&#x521D;&#x59CB;&#x5316;hook&#x5185;&#x8BBE;&#x7F6E;&#x4E86;&#x65AD;&#x70B9;&#xFF1A;&#x7136;&#x540E;&#x542F;&#x52A8;&#x5E94;&#x7528;&#xFF0C;&#x5E94;&#x7528;&#x5728;&#x6267;&#x884C;&#x4E86;<code>Validator</code>&#x7684;&#x6CE8;&#x5165;&#x540E;&#xFF0C;&#x6210;&#x529F;&#x6267;&#x884C;&#x4E86;<code>LocalValidatorFactoryBean</code>&#x7684;&#x521D;&#x59CB;&#x5316;&#x65B9;&#x6CD5;<code>afterPropertiesSet</code>&#xFF1B;&#x4F46;&#x662F;&#x7B14;&#x8005;&#x5728;&#x8FD9;&#x91CC;&#x53D1;&#x73B0;&#xFF0C;&#x8FD9;&#x4E2A;&#x521D;&#x59CB;&#x5316;&#x6267;&#x884C;&#x4E86;&#x4E24;&#x6B21;&#x3002;&#x6070;&#x6070;&#xFF0C;&#x901A;&#x8FC7;<code>this.messageInterpolator</code>&#x8FD9;&#x4E2A;&#x53D8;&#x91CF;&#xFF0C;&#x7B14;&#x8005;&#x5728;&#x7B2C;&#x4E00;&#x6B21;&#x521D;&#x59CB;&#x5316;&#x7684;&#x65F6;&#x5019;&#x67E5;&#x770B;&#x5230;&#x7528;&#x6237;&#x5B9A;&#x4E49;&#x7684;<code>messageResource</code>&#x5DF2;&#x7ECF;&#x52A0;&#x8F7D;&#xFF0C;&#x5982;&#x4E0B;&#x56FE;&#xFF1A;</p><p><img src="https://static.xuqiang.me/public/images/151106.png" alt="messagesource"></p><p>&#x56FE;&#x7247;&#x4E0A;&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x7EA2;&#x6846;&#x662F;&#x5DF2;&#x6210;&#x529F;&#x52A0;&#x8F7D;&#x7684;<code>messagesource</code>&#xFF1B;&#x800C;&#x7B2C;&#x4E8C;&#x4E2A;&#x7EA2;&#x6846;&#x662F;&#x672A;&#x52A0;&#x8F7D;&#x7684;&#x5F62;&#x5F0F;&#xFF1B;&#x5728;&#x7B2C;&#x4E8C;&#x6B21;&#x521D;&#x59CB;&#x5316;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x7B14;&#x8005;&#x5728;<code>userResourceBundle</code>&#x672A;&#x770B;&#x5230;&#x7B14;&#x8005;&#x5B9A;&#x4E49;&#x7684;<code>messagesource</code>&#x503C;&#xFF0C;&#x8DDF;&#x7B2C;&#x4E8C;&#x4E2A;&#x7EA2;&#x6846;&#x5373;&#x672A;&#x52A0;&#x8F7D;&#x7684;&#x5F62;&#x5F0F;&#x662F;&#x4E00;&#x6837;&#x7684;&#x3002;</p><p>&#x5F88;&#x597D;&#xFF0C;&#x6210;&#x529F;&#x5B9A;&#x4F4D;&#x5230;&#x5177;&#x4F53;&#x7684;&#x95EE;&#x9898;&#xFF1A;<code>DataBinder</code>&#x4F7F;&#x7528;&#x7684;<code>validator</code>&#x5B9E;&#x4F8B;&#x5E76;&#x4E0D;&#x662F;&#x7B14;&#x8005;&#x5B9A;&#x4E49;&#x7684;&#x5B9E;&#x4F8B;&#xFF0C;&#x8FD9;&#x4E5F;&#x5C31;&#x662F;&#x4E3A;&#x4EC0;&#x4E48;&#x56FD;&#x9645;&#x5316;&#x59CB;&#x7EC8;&#x65E0;&#x6CD5;&#x751F;&#x6548;&#x7684;&#x539F;&#x56E0;&#x3002;</p><h3 id="&#x89E3;&#x51B3;&#x95EE;&#x9898;"><a href="#&#x89E3;&#x51B3;&#x95EE;&#x9898;" class="headerlink" title="&#x89E3;&#x51B3;&#x95EE;&#x9898;"></a>&#x89E3;&#x51B3;&#x95EE;&#x9898;</h3><p>&#x5B9A;&#x4F4D;&#x5230;&#x95EE;&#x9898;&#x6240;&#x5728;&#xFF0C;&#x5C31;&#x8BE5;&#x601D;&#x8003;&#x5982;&#x4F55;&#x53BB;&#x89E3;&#x51B3;&#x8FD9;&#x4E2A;&#x95EE;&#x9898;&#x3002;</p><p>&#x6309;&#x7406;&#x6765;&#x8BF4;&#xFF0C;<code>Spring Boot</code>&#x5728;&#x7528;&#x6237;&#x81EA;&#x5B9A;&#x4E49;<code>Validator</code>&#x540E;&#xFF0C;&#x4F1A;&#x8986;&#x76D6;&#x5B83;&#x81EA;&#x8EAB;&#x7684;&#x6821;&#x9A8C;&#x5668;&#xFF0C;&#x5B9E;&#x9645;&#x60C5;&#x51B5;&#x6309;&#x7167;&#x7B14;&#x8005;&#x5B9A;&#x4F4D;&#x7684;&#x95EE;&#x9898;&#xFF0C;&#x8FD9;&#x79CD;&#x8986;&#x76D6;&#x60C5;&#x51B5;&#x5E76;&#x6CA1;&#x6709;&#x53D1;&#x751F;&#x3002;</p><p>&#x5728;&#x8FD9;&#x91CC;&#x63D0;&#x4E00;&#x53E5;&#xFF0C;<code>Spring Boot</code>&#x96C6;&#x6210;&#x6821;&#x9A8C;&#x5668;&#x6216;&#x8005;&#x5176;&#x4ED6;&#x4E00;&#x4E9B;&#x6846;&#x67B6;&#x7B49;&#x7B49;&#x90FD;&#x662F;&#x901A;&#x8FC7;<code>Configuration</code>&#x673A;&#x5236;&#x6765;&#x5B9E;&#x73B0;&#xFF08;&#x8FD9;&#x4E2A;&#x53EF;&#x4EE5;&#x770B;&#x7B14;&#x8005;&#x4E4B;&#x524D;&#x5199;&#x7684;&#x4E00;&#x7BC7;&#x6587;&#x7AE0;&#xFF1A;<a href="https://xuqiang.me/Spring-Bean&#x89E3;&#x6790;&#x5206;&#x6790;&#x8FC7;&#x7A0B;.html">Spring-Bean&#x89E3;&#x6790;&#x5206;&#x6790;&#x8FC7;&#x7A0B;</a>&#xFF09;&#x3002;&#x6765;&#x627E;&#x627E;<code>Validator</code>&#x7684;&#x81EA;&#x52A8;&#x5316;&#x914D;&#x7F6E;&#x7C7B;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@ConditionalOnClass</span>(ExecutableValidator.class)</span><br><span class="line"><span class="meta">@ConditionalOnResource</span>(resources = <span class="string">&quot;classpath:META-INF/services/javax.validation.spi.ValidationProvider&quot;</span>)</span><br><span class="line"><span class="meta">@Import</span>(PrimaryDefaultValidatorPostProcessor.class)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ValidationAutoConfiguration</span> </span>{</span><br><span class="line"></span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="meta">@Role</span>(BeanDefinition.ROLE_INFRASTRUCTURE)</span><br><span class="line"><span class="meta">@ConditionalOnMissingBean</span>(Validator.class)</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> LocalValidatorFactoryBean <span class="title">defaultValidator</span><span class="params">()</span> </span>{ &#x2460;</span><br><span class="line">LocalValidatorFactoryBean factoryBean = <span class="keyword">new</span> LocalValidatorFactoryBean();</span><br><span class="line">MessageInterpolatorFactory interpolatorFactory = <span class="keyword">new</span> MessageInterpolatorFactory();</span><br><span class="line">factoryBean.setMessageInterpolator(interpolatorFactory.getObject());</span><br><span class="line"><span class="keyword">return</span> factoryBean;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="meta">@ConditionalOnMissingBean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> MethodValidationPostProcessor <span class="title">methodValidationPostProcessor</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">Environment environment, @Lazy Validator validator)</span> </span>{</span><br><span class="line">MethodValidationPostProcessor processor = <span class="keyword">new</span> MethodValidationPostProcessor();</span><br><span class="line"><span class="keyword">boolean</span> proxyTargetClass = environment</span><br><span class="line">.getProperty(<span class="string">&quot;spring.aop.proxy-target-class&quot;</span>, Boolean.class, <span class="keyword">true</span>);</span><br><span class="line">processor.setProxyTargetClass(proxyTargetClass);</span><br><span class="line">processor.setValidator(validator);</span><br><span class="line"><span class="keyword">return</span> processor;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x53EF;&#x4EE5;&#x5728; &#x2460; &#x5904;&#x770B;&#x5230;&#xFF0C;&#x8FD9;&#x4E2A;&#x5C31;&#x662F;<code>Spring Boot</code>&#x81EA;&#x8EAB;&#x9ED8;&#x8BA4;&#x7684;&#x6821;&#x9A8C;&#x5668;&#x7684;&#x4E00;&#x4E2A;&#x521D;&#x59CB;&#x5316;&#x6CE8;&#x5165;&#x65B9;&#x6CD5;&#x3002;&#x5E76;&#x4E14;&#xFF0C;&#x53EF;&#x4EE5;&#x770B;&#x5230;&#xFF0C;&#x5728;&#x8FD9;&#x91CC;&#x6CA1;&#x6709;&#x6CE8;&#x5165;<code>messageSource</code>&#x3002;</p><p>&#x800C;&#x8FD9;&#x4E2A;&#x65B9;&#x6CD5;&#x4E0A;&#x6709;&#x6807;&#x8BC6;<code>@ConditionalOnMissingBean(Validator.class)</code>&#x6CE8;&#x89E3;&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x8BF4;&#xFF0C;&#x5982;&#x679C;&#x5DF2;&#x7ECF;&#x5B58;&#x5728;<code>Validator</code>&#x7C7B;&#xFF0C;&#x90A3;&#x4E48;&#x4E45;&#x4E0D;&#x4F1A;&#x6267;&#x884C;<code>Spring Boot</code>&#x81EA;&#x8EAB;&#x6821;&#x9A8C;&#x5668;&#x7684;&#x521D;&#x59CB;&#x5316;&#x6D41;&#x7A0B;&#xFF1B;&#x8FD9;&#x4E2A;&#x5C31;&#x5947;&#x602A;&#x4E86;&#xFF0C;&#x4E4B;&#x524D;&#x7B14;&#x8005;&#x81EA;&#x5B9A;&#x4E49;&#x7684;<code>Validator</code>&#x5728;&#x6CE8;&#x5165;&#x540E;&#xFF0C;&#x5E76;&#x6CA1;&#x6709;&#x4F7F;&#x5F97;&#x8FD9;&#x4E2A;&#x521D;&#x59CB;&#x5316;&#x5931;&#x6548;&#x3002;&#x7B14;&#x8005;&#x5C1D;&#x8BD5;&#x5728;&#x8FD9;&#x4E2A;&#x65B9;&#x6CD5;&#x4E0A;&#x52A0;&#x4E86;&#x65AD;&#x70B9;&#xFF0C;&#x542F;&#x52A8;&#x5E94;&#x7528;&#x540E;&#xFF0C;&#x7B14;&#x8005;&#x5B9A;&#x4E49;&#x7684;<code>Validator</code>&#x548C;<code>Spring Boot</code>&#x81EA;&#x8EAB;&#x7684;<code>Validator</code>&#x90FD;&#x6267;&#x884C;&#x4E86;&#x521D;&#x59CB;&#x5316;&#x8FC7;&#x7A0B;&#x3002;</p><p>&#x8FD9;&#x4E2A;&#x65F6;&#x5019;&#xFF0C;&#x7B14;&#x8005;&#x7684;&#x5185;&#x5FC3;&#x771F;&#x7684;&#x662F;&#x5D29;&#x6E83;&#x7684;&#xFF0C;&#x96BE;&#x4E0D;&#x6210;<code>Spring Boot</code>&#x7684;<code>Conditional</code>&#x673A;&#x5236;&#x5931;&#x6548;&#x4E86;&#xFF1F;&#xFF1F;&#xFF1F;</p><p>&#x7A81;&#x7136;&#x60F3;&#x5230;&#xFF0C;<code>ConditionalOnMissingBean</code>&#x662F;&#x6839;&#x636E;&#x7C7B;&#x6765;&#x5224;&#x65AD;&#x7684;&#xFF0C;&#x90A3;&#x4E48;&#x4F1A;&#x4E0D;&#x4F1A;&#x5B58;&#x5728;&#x4E24;&#x4E2A;<code>Validator</code>&#x7C7B;&#xFF1F;&#x7136;&#x540E;&#x5BF9;&#x6BD4;&#x4E86;&#x4E00;&#x4E0B;&#xFF0C;&#x53D1;&#x73B0;&#x4E86;&#x4E00;&#x4E2A;&#x5DE8;&#x5751;&#x65E0;&#x6BD4;&#x7684;&#x4E8B;&#x60C5;&#xFF1A;</p><p>&#x7B14;&#x8005;&#x5F15;&#x5165;&#x7684;&#x5168;&#x9650;&#x5B9A;&#x540D;&#xFF1A;<code>org.springframework.validation.Validator</code><br>&#x800C;<code>Spring Boot</code>&#x652F;&#x6301;&#x7684;&#x5168;&#x9650;&#x5B9A;&#x540D;&#xFF1A;<code>javax.validation.Validator</code></p><p>&#x96BE;&#x602A;&#x4E00;&#x81F4;&#x65E0;&#x6CD5;&#x6210;&#x529F;&#x8986;&#x76D6;&#x9ED8;&#x8BA4;&#x914D;&#x7F6E;&#x3002;</p><p>&#x800C;&#x4E3A;&#x4EC0;&#x4E48;&#x7C7B;&#x5168;&#x9650;&#x5B9A;&#x540D;&#x4E0D;&#x4E00;&#x6837;&#xFF0C;&#x800C;&#x4ECD;&#x65E7;&#x53EF;&#x4EE5;&#x8FD4;&#x56DE;<code>LocalValidatorFactoryBean</code>&#x7C7B;&#x7684;&#x5B9E;&#x4F8B;&#x5462;&#xFF1F;&#x56E0;&#x4E3A;&#xFF0C;<code>LocalValidatorFactoryBean</code>&#x7C7B;&#x7684;&#x7236;&#x7C7B;<code>SpringValidatorAdapter</code>&#x5B9E;&#x73B0;&#x4E86;<code>javax.validation.Validator</code>&#x63A5;&#x53E3;&#x4EE5;&#x53CA;<code>SmartValidator</code>&#x63A5;&#x53E3;&#xFF1B;&#x800C;<code>SmartValidator</code>&#x63A5;&#x53E3;&#x7EE7;&#x627F;&#x4E86;<code>org.springframework.validation.Validator</code>&#x63A5;&#x53E3;&#x3002;&#x6240;&#x4EE5;&#xFF0C;&#x5BF9;<code>LocalValidatorFactoryBean</code>&#x7C7B;&#x7684;&#x5B9E;&#x4F8B;&#x6765;&#x8BF4;&#xFF0C;&#x90FD;&#x53EF;&#x4EE5;&#x517C;&#x5BB9;&#x3002;</p><p>&#x8FD9;&#x4E2A;&#x4E5F;&#x5C31;&#x662F;&#x4E3A;&#x4EC0;&#x4E48;&#x7B14;&#x8005;&#x5728;&#x6267;&#x884C;&#x6821;&#x9A8C;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x6821;&#x9A8C;&#x5668;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x6D88;&#x606F;&#x6A21;&#x677F;&#x800C;&#x4E0D;&#x662F;&#x89E3;&#x6790;&#x540E;&#x7684;&#x6D88;&#x606F;&#x7684;&#x539F;&#x56E0;&#x6240;&#x5728;&#x3002;</p><h2 id="&#x603B;&#x7ED3;"><a href="#&#x603B;&#x7ED3;" class="headerlink" title="&#x603B;&#x7ED3;"></a>&#x603B;&#x7ED3;</h2><p>&#x4E00;&#x53E5;&#x8BDD;&#xFF0C;&#x5F15;&#x5165;&#x7C7B;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x4EE5;&#x540E;&#x8FD8;&#x662F;&#x8981;&#x4ED4;&#x7EC6;&#x70B9;&#x3002;</p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;笔者在最近应用国际化校验的时候，碰到一个奇怪的问题：国际化始终不能生效，消息返回的仍旧是模板消息。&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="i18n" scheme="https://xuqiang.me/tags/i18n/"/>
    
      <category term="jsr303" scheme="https://xuqiang.me/tags/jsr303/"/>
    
  </entry>
  
  <entry>
    <title>一致性hash应用于分布式数据处理</title>
    <link href="https://xuqiang.me/%E4%B8%80%E8%87%B4%E6%80%A7hash%E5%BA%94%E7%94%A8%E4%BA%8E%E5%88%86%E5%B8%83%E5%BC%8F%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86.html"/>
    <id>https://xuqiang.me/一致性hash应用于分布式数据处理.html</id>
    <published>2018-10-19T14:44:20.000Z</published>
    <updated>2018-10-19T17:07:01.627Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x6700;&#x8FD1;&#x4E00;&#x4E2A;&#x4EFB;&#x52A1;&#x662F;&#x505A;&#x4E00;&#x4E2A;&#x722C;&#x866B;&#xFF0C;&#x800C;&#x5728;&#x8FD9;&#x4E2A;&#x6846;&#x67B6;&#x6784;&#x5EFA;&#x8FC7;&#x7A0B;&#x4E2D;&#x9700;&#x8981;&#x505A;&#x5230;&#x5E73;&#x6ED1;&#x6C34;&#x5E73;&#x6269;&#x5C55;&#xFF1B;&#x56E0;&#x6B64;&#xFF0C;&#x5BF9;&#x4E8E;&#x91C7;&#x96C6;&#x5668;&#x800C;&#x8A00;&#xFF0C;&#x76F4;&#x63A5;&#x66FF;&#x6362;&#x65E7;&#x6570;&#x636E;&#x5373;&#x53EF;&#xFF1B;&#x800C;&#x5BF9;&#x4E8E;&#x5206;&#x6790;&#x5668;&#x800C;&#x8A00;&#xFF0C;&#x603B;&#x4E0D;&#x80FD;&#x91CD;&#x590D;&#x89E3;&#x6790;&#x76F8;&#x540C;&#x6570;&#x636E;&#xFF0C;&#x8FD9;&#x4F1A;&#x9020;&#x6210;&#x4E25;&#x91CD;&#x7684;&#x6027;&#x80FD;&#x6D6A;&#x8D39;&#xFF0C;&#x7279;&#x522B;&#x662F;&#x5728;&#x6B64;&#x8FC7;&#x7A0B;&#x4E2D;&#x9700;&#x8981;&#x4F7F;&#x7528;OCR&#x6765;&#x5206;&#x6790;&#x56FE;&#x7247;&#x3002;&#x6240;&#x4EE5;&#xFF0C;&#x60F3;&#x5230;&#x5C06;&#x4E00;&#x81F4;&#x6027;hash&#x7B97;&#x6CD5;&#x5E94;&#x7528;&#x5230;&#x5206;&#x5E03;&#x5F0F;&#x6570;&#x636E;&#x5904;&#x7406;&#x4E2D;&#x3002;</p><a id="more"></a><h3 id="&#x4F55;&#x4E3A;&#x4E00;&#x81F4;&#x6027;hash&#x7B97;&#x6CD5;"><a href="#&#x4F55;&#x4E3A;&#x4E00;&#x81F4;&#x6027;hash&#x7B97;&#x6CD5;" class="headerlink" title="&#x4F55;&#x4E3A;&#x4E00;&#x81F4;&#x6027;hash&#x7B97;&#x6CD5;"></a>&#x4F55;&#x4E3A;&#x4E00;&#x81F4;&#x6027;hash&#x7B97;&#x6CD5;</h3><p><img src="https://static.xuqiang.me/public/images/151910.jpg" alt="&#x4E00;&#x81F4;&#x6027;hash&#x73AF;"></p><p>&#x6765;&#x6E90;&#xFF1A;&#x5728;&#x4E00;&#x81F4;&#x6027;hash&#x7B97;&#x6CD5;&#x4E4B;&#x524D;&#xFF0C;&#x5982;&#x679C;&#x9700;&#x8981;&#x89E3;&#x51B3;&#x591A;&#x4E2A;&#x670D;&#x52A1;&#x5668;&#x5185;&#x4E0D;&#x540C;&#x7F13;&#x5B58;&#x7684;&#x5747;&#x5300;&#x5206;&#x5E03;&#xFF0C;&#x901A;&#x8FC7; m=hash(o)%n &#x8FD9;&#x4E2A;&#x516C;&#x5F0F;&#x4F5C;&#x4E3A;&#x57FA;&#x7840;&#x8FDB;&#x884C;&#xFF1B;&#x5373;&#x5728;&#x591A;&#x4E2A;&#x7F13;&#x5B58;&#x670D;&#x52A1;&#x5668;&#x5185;&#xFF0C;&#x5C06;&#x4E0D;&#x540C;&#x7684;&#x5BF9;&#x8C61;&#x5747;&#x5300;&#x7684;&#x5206;&#x6563;&#x7F13;&#x5B58;&#x5230;&#x8FD9;&#x4E9B;&#x7F13;&#x5B58;&#x670D;&#x52A1;&#x5668;&#x5185;&#xFF1B;&#x4F46;&#x662F;&#x5982;&#x679C;&#x51FA;&#x73B0;&#x4E00;&#x53F0;&#x673A;&#x5668;down&#x6389;&#x6216;&#x8005;&#x589E;&#x52A0;&#x4E86;&#x4E00;&#x6761;&#x673A;&#x5668;&#xFF0C;&#x90A3;&#x4E48;&#x6839;&#x636E;&#x4E4B;&#x524D;&#x7684;&#x516C;&#x5F0F;&#xFF0C;&#x51E0;&#x4E4E;&#x6240;&#x6709;&#x7684;&#x7F13;&#x5B58;&#x4F4D;&#x7F6E;&#x90FD;&#x5C06;&#x53D1;&#x751F;&#x53D8;&#x5316;&#xFF0C;&#x9020;&#x6210;&#x7F13;&#x5B58;&#x5185;&#x5BB9;&#x5931;&#x6548;&#x3002;</p><p>&#x89E3;&#x51B3;&#x65B9;&#x6848;&#xFF1A;&#x4E0D;&#x5BF9;&#x670D;&#x52A1;&#x5668;&#x6570;&#x91CF;&#x53D6;&#x6A21;&#xFF0C;&#x800C;&#x662F;&#x5BF9;2^32&#x6B21;&#x53D6;&#x6A21;&#xFF1B;2^32-1&#x4E2A;&#x70B9;&#x7EC4;&#x6210;&#x4E00;&#x4E2A;&#x73AF;&#xFF0C;&#x5C06;&#x670D;&#x52A1;&#x5668;&#x6620;&#x5C04;&#x5230;&#x8FD9;&#x4E2A;&#x73AF;&#x4E0A;&#x7684;&#x70B9;&#xFF1B;&#x6839;&#x636E;key hash&#x540E;&#x6240;&#x5904;&#x73AF;&#x4E0A;&#x7684;&#x70B9;&#xFF0C;&#x6309;&#x7167;&#x987A;&#x65F6;&#x9488;&#x83B7;&#x53D6;&#x6700;&#x8FD1;&#x7684;&#x670D;&#x52A1;&#x5668;&#x8282;&#x70B9;&#xFF0C;&#x5373;&#x5C06;&#x8BE5;&#x5185;&#x5BB9;&#x7F13;&#x5B58;&#x5230;&#x8FD9;&#x4E2A;&#x670D;&#x52A1;&#x5668;&#x4E0A;&#x3002;&#x8FD9;&#x5C31;&#x4F7F;&#x5F97;&#xFF0C;&#x5373;&#x4F7F;&#x6709;&#x90E8;&#x5206;&#x670D;&#x52A1;&#x5668;&#x8282;&#x70B9;down&#x6389;&#xFF0C;down&#x6389;&#x8282;&#x70B9;&#x7684;&#x7F13;&#x5B58;&#x5185;&#x5BB9;&#x6309;&#x7167;&#x987A;&#x65F6;&#x9488;&#x83B7;&#x53D6;&#x65B0;&#x7684;&#x7F13;&#x5B58;&#x670D;&#x52A1;&#x5668;&#xFF1B;&#x5373;&#xFF0C;&#x5E76;&#x4E0D;&#x662F;&#x6240;&#x6709;&#x7684;&#x7F13;&#x5B58;&#x4F1A;&#x5931;&#x6548;&#x3002;&#x8FD9;&#x5C31;&#x662F;&#x76F8;&#x5BF9;&#x4E8E;&#x670D;&#x52A1;&#x5668;&#x6570;&#x91CF;&#x53D6;&#x6A21;&#x7684;&#x4F18;&#x70B9;&#x3002;</p><p>&#x63D0;&#x5347;&#xFF1A;&#x4E0A;&#x8FF0;&#x7684;&#x4E00;&#x81F4;&#x6027;hash&#x7B97;&#x6CD5;&#x4ECD;&#x65E7;&#x5B58;&#x5728;&#x4E00;&#x4E2A;&#x95EE;&#x9898;&#xFF0C;&#x4E0A;&#x8FF0;&#x63CF;&#x8FF0;&#x57FA;&#x4E8E;&#x7684;&#x4E00;&#x4E2A;&#x524D;&#x63D0;&#x662F;&#xFF0C;&#x5404;&#x4E2A;&#x670D;&#x52A1;&#x5668;&#x5206;&#x5E03;&#x5747;&#x5300;&#x3002;&#x5982;&#x679C;&#x5206;&#x5E03;&#x4E0D;&#x5747;&#x5300;&#x51FA;&#x73B0;&#x6781;&#x7AEF;&#x60C5;&#x51B5;&#xFF0C;&#x90A3;&#x4E48;&#x5C31;&#x53EF;&#x80FD;&#x4F1A;&#x51FA;&#x73B0;&#x5927;&#x91CF;&#x751A;&#x81F3;&#x6240;&#x6709;&#x7684;&#x5185;&#x5BB9;&#x90FD;&#x7F13;&#x5B58;&#x5230;&#x540C;&#x4E00;&#x4E2A;&#x670D;&#x52A1;&#x5668;&#x8282;&#x70B9;&#x4E0A;&#xFF0C;&#x8FD9;&#x79CD;&#x73B0;&#x8C61;&#x88AB;&#x79F0;&#x4E3A;hash&#x73AF;&#x7684;&#x504F;&#x659C;&#x3002;&#x8FD9;&#x65F6;&#x5019;&#xFF0C;&#x53EA;&#x9700;&#x8981;&#x5C06;&#x8FD9;&#x4E9B;&#x7269;&#x7406;&#x670D;&#x52A1;&#x5668;&#x8282;&#x70B9;&#x590D;&#x5236;&#x591A;&#x4E2A;&#x5206;&#x6563;&#x5230;&#x8FD9;&#x4E2A;hash&#x73AF;&#x4E0A;&#xFF0C;&#x90A3;&#x4E48;&#x5C31;&#x80FD;&#x591F;&#x5C3D;&#x91CF;&#x51CF;&#x5C11;&#x8FD9;&#x79CD;&#x504F;&#x659C;&#x7684;&#x60C5;&#x51B5;&#x53D1;&#x751F;&#x3002;&#x5982;&#x4F55;&#x590D;&#x5236;&#xFF1F;&#x53EA;&#x8981;&#x4EE5;&#x7269;&#x7406;&#x8282;&#x70B9;&#x4E3A;&#x57FA;&#x7840;&#x5EFA;&#x7ACB;&#x591A;&#x4E2A;&#x865A;&#x62DF;&#x8282;&#x70B9;&#xFF0C;&#x8FD9;&#x4E9B;&#x865A;&#x62DF;&#x8282;&#x70B9;&#x6307;&#x5411;&#x7269;&#x7406;&#x670D;&#x52A1;&#x5668;&#x5373;&#x53EF;&#x3002;</p><p>&#x66F4;&#x4E3A;&#x8BE6;&#x7EC6;&#x7684;&#x4E00;&#x81F4;&#x6027;hash&#x7B97;&#x6CD5;&#x89E3;&#x8BF4;&#xFF0C;<a href="http://www.zsythink.net/archives/1182" target="_blank" rel="noopener">&#x53EF;&#x4EE5;&#x67E5;&#x770B;&#x8FD9;&#x7BC7;&#x6587;&#x7AE0;</a>&#x3002;</p><h3 id="&#x5206;&#x5E03;&#x5F0F;&#x6570;&#x636E;&#x5904;&#x7406;&#x601D;&#x8DEF;"><a href="#&#x5206;&#x5E03;&#x5F0F;&#x6570;&#x636E;&#x5904;&#x7406;&#x601D;&#x8DEF;" class="headerlink" title="&#x5206;&#x5E03;&#x5F0F;&#x6570;&#x636E;&#x5904;&#x7406;&#x601D;&#x8DEF;"></a>&#x5206;&#x5E03;&#x5F0F;&#x6570;&#x636E;&#x5904;&#x7406;&#x601D;&#x8DEF;</h3><p>&#x4E86;&#x89E3;&#x8FC7;&#x4E00;&#x81F4;&#x6027;hash&#x7B97;&#x6CD5;&#xFF0C;&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x672C;&#x8D28;&#x4E0A;&#x5C31;&#x662F;&#x4E3A;&#x4E86;&#x4F7F;&#x5F97;&#x7F13;&#x5B58;&#x5185;&#x5BB9;&#x5747;&#x5300;&#x5206;&#x4E0D;&#x5230;&#x4E0D;&#x540C;&#x7684;&#x670D;&#x52A1;&#x5668;&#xFF0C;&#x5E76;&#x4E14;&#x80FD;&#x591F;&#x4F7F;&#x5F97;&#x5728;&#x589E;&#x52A0;&#x6216;&#x8005;&#x5220;&#x9664;&#x670D;&#x52A1;&#x5668;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x5C3D;&#x91CF;&#x51CF;&#x5C11;&#x5BF9;&#x5176;&#x4ED6;&#x7F13;&#x5B58;&#x5185;&#x5BB9;&#x7684;&#x5F71;&#x54CD;&#x3002;&#x800C;&#x5206;&#x5E03;&#x5F0F;&#x6570;&#x636E;&#x5904;&#x7406;&#xFF0C;&#x5176;&#x5B9E;&#x4E5F;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x8FD9;&#x4E2A;&#x601D;&#x8DEF;&#x3002;</p><ol><li>&#x6784;&#x5EFA;&#x4E00;&#x4E2A;&#x4EE5;&#x6570;&#x636E;&#x5904;&#x7406;&#x670D;&#x52A1;&#x5668;&#x6620;&#x5C04;&#x51FA;&#x6765;&#x7684;N&#x591A;&#x865A;&#x62DF;&#x8282;&#x70B9;&#x6240;&#x5728;&#x7684;&#x4E00;&#x81F4;&#x6027;hash&#x73AF;</li><li>&#x5C06;&#x5BF9;&#x8C61;key&#x7684;hash&#x8BA1;&#x7B97;&#xFF0C;&#x6309;&#x7167;&#x987A;&#x65F6;&#x9488;&#x83B7;&#x53D6;&#x6570;&#x636E;&#x5904;&#x7406;&#x670D;&#x52A1;&#x5668;</li><li>&#x5224;&#x65AD;&#x83B7;&#x53D6;&#x7684;&#x6570;&#x636E;&#x5904;&#x7406;&#x670D;&#x52A1;&#x5668;&#x662F;&#x5426;&#x4E0E;&#x5F53;&#x524D;&#x7684;&#x670D;&#x52A1;&#x5668;&#x4E00;&#x81F4;&#xFF0C;&#x5982;&#x679C;&#x4E00;&#x81F4;&#xFF0C;&#x5219;&#x76F4;&#x63A5;&#x5904;&#x7406;&#x6570;&#x636E;&#xFF0C;&#x5426;&#x5219;&#x5FFD;&#x7565;</li></ol><h3 id="&#x5B9E;&#x73B0;"><a href="#&#x5B9E;&#x73B0;" class="headerlink" title="&#x5B9E;&#x73B0;"></a>&#x5B9E;&#x73B0;</h3><ol><li>&#x6240;&#x6709;&#x5206;&#x6790;&#x5668;&#x5E94;&#x7528;&#x6CE8;&#x518C;&#x5230;ZK&#x6CE8;&#x518C;&#x4E2D;&#x5FC3;</li></ol><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> ZkLifeCycle <span class="title">zkLifeCycle</span><span class="params">()</span> </span>{</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> ZkLifeCycle();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * ZK&#x6CE8;&#x518C;</span></span><br><span class="line"><span class="comment">  * </span></span><br><span class="line"><span class="comment">  * &#x76D1;&#x542C;Spring&#x7684;&#x751F;&#x547D;&#x5468;&#x671F;&#xFF0C;&#x5728;&#x4E0A;&#x4E0B;&#x6587;&#x5237;&#x65B0;&#x5B8C;&#x6210;&#x540E;&#xFF0C;&#x6267;&#x884C;ZK&#x5BA2;&#x6237;&#x7AEF;&#x7684;&#x6CE8;&#x518C;</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">ZkLifeCycle</span> <span class="keyword">implements</span> <span class="title">ApplicationListener</span>&lt;<span class="title">ContextRefreshedEvent</span>&gt; </span>{</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onApplicationEvent</span><span class="params">(ContextRefreshedEvent event)</span> </span>{</span><br><span class="line">        ApplicationContext context = event.getApplicationContext();</span><br><span class="line">        ZkClient zkClient = context.getBean(ZkClient.class);</span><br><span class="line">        zkClient.register();</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">``` </span><br><span class="line"></span><br><span class="line"><span class="number">2</span>. &#x6BCF;&#x4E2A;&#x5206;&#x6790;&#x5668;&#x5E94;&#x7528;&#x5728;&#x542F;&#x52A8;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x901A;&#x8FC7;ZK&#x7684;&#x5BA2;&#x6237;&#x7AEF;&#x7F13;&#x5B58;&#x5206;&#x6790;&#x5668;&#x5E94;&#x7528;&#x5217;&#x8868;  </span><br><span class="line"></span><br><span class="line">```java</span><br><span class="line">client.getConnectionStateListenable().addListener((curatorFramework, newState) -&gt; {</span><br><span class="line">    <span class="comment">// &#x7B2C;&#x4E00;&#x6B21;&#x8FDE;&#x63A5;&#x6216;&#x8005;&#x91CD;&#x65B0;&#x8FDE;&#x63A5;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x521D;&#x59CB;&#x5316;&#x5B9E;&#x4F8B;&#x5217;&#x8868;</span></span><br><span class="line">    <span class="keyword">if</span> (ConnectionState.CONNECTED.equals(newState)</span><br><span class="line">            || ConnectionState.RECONNECTED.equals(newState)) {</span><br><span class="line">        List&lt;String&gt; instances = getInstances();</span><br><span class="line">        instances.forEach(nodeHolder::addPhyNode);</span><br><span class="line">    }</span><br><span class="line">});</span><br></pre></td></tr></tbody></table></figure><ol start="3"><li>&#x76D1;&#x542C;ZK&#x7684;&#x8282;&#x70B9;&#x53D8;&#x66F4;&#x4E8B;&#x4EF6;&#xFF1A;</li></ol><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5BF9;&#x4E8E;&#x8282;&#x70B9;&#x589E;&#x52A0;&#x9ED8;&#x8BA4;&#x76D1;&#x542C;&#x5668;</span></span><br><span class="line">PathChildrenCache watcher = <span class="keyword">new</span> PathChildrenCache(client, rootPath, <span class="keyword">true</span>, <span class="keyword">false</span>, executorService);</span><br><span class="line">watcher.getListenable().addListener((curatorFramework, pathChildrenCacheEvent) -&gt; {</span><br><span class="line">    <span class="keyword">switch</span> (pathChildrenCacheEvent.getType()) {</span><br><span class="line">        <span class="keyword">case</span> CHILD_ADDED:</span><br><span class="line">            <span class="comment">// &#x8282;&#x70B9;&#x589E;&#x52A0;</span></span><br><span class="line">            nodeHolder.addPhyNode(getNodePath(pathChildrenCacheEvent.getData().getPath()));</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> CHILD_REMOVED:</span><br><span class="line">            <span class="comment">// &#x8282;&#x70B9;&#x5220;&#x9664;</span></span><br><span class="line">            nodeHolder.delPhyNode(getNodePath(pathChildrenCacheEvent.getData().getPath()));</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">    }</span><br><span class="line">});</span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line">    watcher.start();</span><br><span class="line">} <span class="keyword">catch</span> (Exception e) {</span><br><span class="line">    log.error(<span class="string">&quot;&#x5B50;&#x8282;&#x70B9;&#x72B6;&#x6001;&#x76D1;&#x542C;&#x5668;&#x542F;&#x52A8;&#x5931;&#x8D25;: {}&quot;</span>, e.getMessage());</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x53EA;&#x6709;&#x5F53;&#x5176;&#x4ED6;&#x5BA2;&#x6237;&#x7AEF;&#x88AB;&#x5220;&#x9664;&#x6216;&#x8005;&#x589E;&#x52A0;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x624D;&#x4F1A;&#x89E6;&#x53D1;&#x8282;&#x70B9;&#x6301;&#x6709;&#x5BB9;&#x5668;&#x7684;&#x589E;&#x52A0;&#x7269;&#x7406;&#x8282;&#x70B9;&#x548C;&#x5220;&#x9664;&#x7269;&#x7406;&#x8282;&#x70B9;&#x64CD;&#x4F5C;&#x3002;</p><ol start="4"><li>&#x83B7;&#x53D6;&#x5BF9;&#x8C61;key&#x7684;hash&#x503C;&#xFF0C;&#x6839;&#x636E;hash&#x503C;&#x6BD4;&#x8F83;&#x83B7;&#x53D6;&#x865A;&#x62DF;&#x8282;&#x70B9;</li></ol><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">VirtualServerNode node = nodeHolder.getServerNode(houseId);</span><br><span class="line"></span><br><span class="line"><span class="comment">// &#x60F3;&#x8981;&#x5904;&#x7406;&#x7684;&#x6570;&#x636E;&#x88AB;&#x5212;&#x5206;&#x5230;&#x5F53;&#x524D;&#x7269;&#x7406;&#x8282;&#x70B9;&#x7684;&#x865A;&#x62DF;&#x8282;&#x70B9;&#xFF0C;&#x5219;&#x52A0;&#x5165;&#x5904;&#x7406;&#x5217;&#x8868;</span></span><br><span class="line"><span class="keyword">if</span> (node != <span class="keyword">null</span> &amp;&amp; StringUtils.contains(node.getServerNode(), getCurrentServerName())) {</span><br><span class="line">    list.add(ziruHostingHouseMetadata);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h4 id="&#x8282;&#x70B9;&#x6301;&#x6709;&#x5BB9;&#x5668;&#x7684;&#x5B9E;&#x73B0;"><a href="#&#x8282;&#x70B9;&#x6301;&#x6709;&#x5BB9;&#x5668;&#x7684;&#x5B9E;&#x73B0;" class="headerlink" title="&#x8282;&#x70B9;&#x6301;&#x6709;&#x5BB9;&#x5668;&#x7684;&#x5B9E;&#x73B0;"></a>&#x8282;&#x70B9;&#x6301;&#x6709;&#x5BB9;&#x5668;&#x7684;&#x5B9E;&#x73B0;</h4><p>&#x5728;&#x8282;&#x70B9;&#x6301;&#x6709;&#x5BB9;&#x5668;&#x5185;&#xFF0C;&#x901A;&#x8FC7;ArrayList&#x6570;&#x636E;&#x7ED3;&#x6784;&#x6765;&#x5B58;&#x50A8;&#x865A;&#x62DF;&#x8282;&#x70B9;&#xFF1B;&#x5E76;&#x4E14;&#x6301;&#x6709;&#x4E00;&#x4E2A;Set&#x96C6;&#x5408;&#xFF0C;&#x7528;&#x6765;&#x5B58;&#x50A8;&#x7269;&#x7406;&#x8282;&#x70B9;&#x7684;&#x8282;&#x70B9;&#x540D;&#xFF0C;&#x9632;&#x6B62;&#x51FA;&#x73B0;&#x91CD;&#x590D;&#x6DFB;&#x52A0;&#x7684;&#x60C5;&#x51B5;&#x53D1;&#x751F;&#x3002;&#x540C;&#x65F6;&#xFF0C;&#x5728;&#x589E;&#x52A0;&#x7269;&#x7406;&#x8282;&#x70B9;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x4F1A;&#x5C06;&#x8BE5;&#x7269;&#x7406;&#x8282;&#x70B9;&#x6620;&#x5C04;&#x4E3A;5&#x4E2A;&#x865A;&#x62DF;&#x8282;&#x70B9;&#xFF0C;&#x5E76;&#x4EE5;128bit&#x7684;hash&#x7ED3;&#x679C;&#x987A;&#x5E8F;&#x6392;&#x5E8F;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * &#x865A;&#x62DF;&#x8282;&#x70B9;&#x5BB9;&#x5668;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> WhatAKitty</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2018/10/16</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Slf</span>4j</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">VirtualServerNodeHolder</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> String VIRTUAL_SPLIT = <span class="string">&quot;&amp;&amp;VN&quot;</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> <span class="keyword">int</span> VIRTUAL_NUM = <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">int</span> seed;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x7269;&#x7406;&#x8282;&#x70B9;&#x540D;&#x79F0;&#x96C6;&#x5408;</span></span><br><span class="line"><span class="comment">     * &#x7528;&#x4E8E;&#x5224;&#x91CD;&#xFF0C;&#x9632;&#x6B62;&#x76F8;&#x540C;&#x8282;&#x70B9;&#x91CD;&#x590D;&#x52A0;&#x5165;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Set&lt;String&gt; names;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> List&lt;VirtualServerNode&gt; nodes;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">VirtualServerNodeHolder</span><span class="params">(<span class="keyword">int</span> seed)</span> </span>{</span><br><span class="line">        <span class="keyword">this</span>.seed = seed;</span><br><span class="line">        <span class="keyword">this</span>.names = <span class="keyword">new</span> HashSet&lt;&gt;();</span><br><span class="line">        <span class="keyword">this</span>.nodes = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">VirtualServerNodeHolder</span><span class="params">(<span class="keyword">int</span> seed, List&lt;VirtualServerNode&gt; nodes)</span> </span>{</span><br><span class="line">        <span class="keyword">this</span>.seed = seed;</span><br><span class="line">        <span class="keyword">this</span>.names = nodes.stream().map(VirtualServerNode::getServerNode).collect(Collectors.toSet());</span><br><span class="line">        <span class="keyword">this</span>.nodes = nodes;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title">addPhyNode</span><span class="params">(String serverName)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (serverName == <span class="keyword">null</span> || nodes.isEmpty()) {</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// hook &#x5224;&#x65AD;&#x662F;&#x5426;&#x5B58;&#x5728;&#x76F8;&#x540C;&#x540D;&#x79F0;&#x8282;&#x70B9;</span></span><br><span class="line">        <span class="keyword">if</span> (names.contains(serverName)) {</span><br><span class="line">            log.error(<span class="string">&quot;&#x5DF2;&#x7ECF;&#x5B58;&#x5728;&#x76F8;&#x540C;&#x540D;&#x79F0;&#x8282;&#x70B9; {}&#xFF0C;&#x5FFD;&#x7565;&#x8BE5;&#x8282;&#x70B9;&quot;</span>, serverName);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        }</span><br><span class="line">        names.add(serverName);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; VIRTUAL_NUM; i++) {</span><br><span class="line">            <span class="comment">// &#x8BBE;&#x5B9A;&#x865A;&#x62DF;&#x8282;&#x70B9;&#x7684;&#x540D;&#x5B57;&#x683C;&#x5F0F;&#x4E3A;&#xFF1A;serverName + &quot;&amp;&amp;VN&quot; + i&#xFF0C;&#x65B9;&#x4FBF;&#x4ECE;&#x865A;&#x62DF;&#x8282;&#x70B9;&#x5F97;&#x5230;&#x7269;&#x7406;&#x8282;&#x70B9;</span></span><br><span class="line">            String virtualServerNodeName = serverName + VIRTUAL_SPLIT + i;</span><br><span class="line">            MurmurHash3.HashValue hash = getHash(virtualServerNodeName);</span><br><span class="line">            VirtualServerNode vsNode = <span class="keyword">new</span> VirtualServerNode(virtualServerNodeName, hash);</span><br><span class="line">            nodes.add(vsNode);</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">//&#x5C06;&#x865A;&#x62DF;&#x8282;&#x70B9;&#x5217;&#x8868;&#x8FDB;&#x884C;&#x6392;&#x5E8F;</span></span><br><span class="line">        Collections.sort(nodes);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title">delPhyNode</span><span class="params">(String serverName)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (serverName == <span class="keyword">null</span> || nodes.isEmpty()) {</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; VIRTUAL_NUM; i++) {</span><br><span class="line">            VirtualServerNode node = nodes.get(i);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (node.getServerNode().contains(serverName)) {</span><br><span class="line">                nodes.remove(node);</span><br><span class="line">                i--;</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// &#x5B8C;&#x6210;&#x6240;&#x6709;&#x8282;&#x70B9;&#x5220;&#x9664;&#x540E;&#xFF0C;&#x5220;&#x9664;&#x540D;&#x5B57;</span></span><br><span class="line">        names.remove(serverName);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Nullable</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> VirtualServerNode <span class="title">getServerNode</span><span class="params">(String key)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (nodes.isEmpty()) {</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">//&#x5F97;&#x5230;key&#x7684;hash&#x503C;</span></span><br><span class="line">        MurmurHash3.HashValue hash = getHash(key);</span><br><span class="line">        <span class="keyword">for</span> (VirtualServerNode node : nodes) {</span><br><span class="line">            <span class="keyword">if</span> (VirtualServerNode.compareTo(node.getNodeHash(), hash) == <span class="number">1</span>) {</span><br><span class="line">                <span class="keyword">return</span> node;</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">//&#x5982;&#x679C;&#x6CA1;&#x6709;&#x627E;&#x5230;&#xFF0C;&#x5219;&#x8BF4;&#x660E;&#x6B64;key&#x7684;hash&#x503C;&#x6BD4;&#x6240;&#x6709;&#x670D;&#x52A1;&#x5668;&#x8282;&#x70B9;&#x7684;hash&#x503C;&#x90FD;&#x5927;&#xFF0C;&#x56E0;&#x6B64;&#x8FD4;&#x56DE;&#x6700;&#x5C0F;hash&#x503C;&#x7684;&#x90A3;&#x4E2A;Server&#x8282;&#x70B9;</span></span><br><span class="line">        <span class="keyword">return</span> nodes.get(<span class="number">0</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x83B7;&#x53D6;&#x7269;&#x7406;&#x8282;&#x70B9;&#x540D;&#x79F0;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">getPhyName</span><span class="params">(VirtualServerNode virtualServerNode)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> StringUtils.substringBeforeLast(virtualServerNode.getServerNode(), VIRTUAL_SPLIT);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> List&lt;VirtualServerNode&gt; <span class="title">getNodes</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> nodes;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> MurmurHash3.<span class="function">HashValue <span class="title">getHash</span><span class="params">(String key)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> MurmurHash3.murmurhash3_x64_128(key, seed);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x8FD9;&#x91CC;&#x9700;&#x8981;&#x989D;&#x5916;&#x8BF4;&#x660E;Hash&#x7684;&#x7B97;&#x6CD5;&#x91C7;&#x7528;&#xFF0C;MurmurHash3&#x7684;&#x5177;&#x4F53;&#x7B97;&#x6CD5;&#x3002;&#x8FD9;&#x79CD;&#x7B97;&#x6CD5;&#x76F8;&#x5BF9;&#x4E8E;&#x5176;&#x4ED6;hash&#x7B97;&#x6CD5;&#xFF0C;&#x66F4;&#x5747;&#x5300;&#x4E14;&#x6548;&#x7387;&#x4E0A;&#x66F4;&#x9AD8;&#x3002;<a href="https://zh.wikipedia.org/wiki/Murmur&#x54C8;&#x5E0C;" target="_blank" rel="noopener">&#x60F3;&#x8981;&#x5177;&#x4F53;&#x4E86;&#x89E3;&#xFF0C;&#x53EF;&#x4EE5;&#x53C2;&#x8003;w&#x7EF4;&#x57FA;&#x767E;&#x79D1;&#x7684;&#x8BF4;&#x660E;</a>&#x3002;</p><p>Java&#x8BA1;&#x7B97;&#x51FA;&#x7684;Murmurhash3&#x662F;&#x4E24;&#x4E2A;64bit&#x7684;long&#x6570;&#x503C;&#xFF0C;&#x8FD9;&#x91CC;&#x901A;&#x8FC7;BigInteger&#x6765;&#x8FDB;&#x884C;&#x76F8;&#x52A0;&#x8BA1;&#x7B97;&#xFF0C;&#x5E76;&#x505A;&#x4E24;&#x4E24;&#x6BD4;&#x8F83;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">compareTo</span><span class="params">(MurmurHash3.HashValue v1, MurmurHash3.HashValue v2)</span> </span>{</span><br><span class="line">    BigInteger one = BigInteger.valueOf(v1.val1).add(BigInteger.valueOf(v1.val2));</span><br><span class="line">    BigInteger another = BigInteger.valueOf(v2.val1).add(BigInteger.valueOf(v2.val2));</span><br><span class="line">    <span class="keyword">return</span> one.compareTo(another);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="&#x603B;&#x7ED3;"><a href="#&#x603B;&#x7ED3;" class="headerlink" title="&#x603B;&#x7ED3;"></a>&#x603B;&#x7ED3;</h3><p>OK&#xFF0C;&#x7ED3;&#x675F;</p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;最近一个任务是做一个爬虫，而在这个框架构建过程中需要做到平滑水平扩展；因此，对于采集器而言，直接替换旧数据即可；而对于分析器而言，总不能重复解析相同数据，这会造成严重的性能浪费，特别是在此过程中需要使用OCR来分析图片。所以，想到将一致性hash算法应用到分布式数据处理中。&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="Distributed" scheme="https://xuqiang.me/categories/Java/Distributed/"/>
    
      <category term="Zookeeper" scheme="https://xuqiang.me/categories/Java/Distributed/Zookeeper/"/>
    
      <category term="Hash" scheme="https://xuqiang.me/categories/Java/Distributed/Zookeeper/Hash/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="Consistent Hashing" scheme="https://xuqiang.me/tags/Consistent-Hashing/"/>
    
      <category term="zookeeper" scheme="https://xuqiang.me/tags/zookeeper/"/>
    
      <category term="murmurhash3" scheme="https://xuqiang.me/tags/murmurhash3/"/>
    
      <category term="distributed" scheme="https://xuqiang.me/tags/distributed/"/>
    
      <category term="curator" scheme="https://xuqiang.me/tags/curator/"/>
    
  </entry>
  
  <entry>
    <title>finally-return在JVM级别的解释</title>
    <link href="https://xuqiang.me/finally-return%E5%9C%A8JVM%E7%BA%A7%E5%88%AB%E7%9A%84%E8%A7%A3%E9%87%8A.html"/>
    <id>https://xuqiang.me/finally-return在JVM级别的解释.html</id>
    <published>2018-09-25T11:18:02.000Z</published>
    <updated>2018-09-25T11:26:12.556Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x521A;&#x770B;&#x4E86;&#x6781;&#x5BA2;&#x65F6;&#x95F4;&#x5173;&#x4E8E;JVM&#x5F02;&#x5E38;&#x7684;&#x76F8;&#x5173;&#x4FE1;&#x606F;&#xFF0C;&#x7136;&#x540E;&#x5728;&#x8BC4;&#x8BBA;&#x91CC;&#x770B;&#x5230;&#x8FD9;&#x4E48;&#x4E00;&#x6761;&#xFF1A;</p><blockquote><p>&#x5982;&#x679C;finally&#x6709;return&#x8BED;&#x53E5;&#xFF0C;catch&#x5185;throw&#x7684;&#x5F02;&#x5E38;&#x4F1A;&#x88AB;&#x5FFD;&#x7565;&#xFF0C;&#x8FD9;&#x4E2A;&#x4ECE;jvm&#x5C42;&#x9762;&#x600E;&#x4E48;&#x89E3;&#x91CA;&#x5462;&#xFF1F;<br>2018-09-02<br>&#xE608; &#x4F5C;&#x8005;&#x56DE;&#x590D;<br>catch&#x91CC;&#x629B;&#x7684;&#x5F02;&#x5E38;&#x4F1A;&#x88AB;finally&#x6355;&#x83B7;&#x4E86;&#xFF0C;&#x518D;&#x6267;&#x884C;&#x5B8C;finally&#x4EE3;&#x7801;&#x540E;&#x91CD;&#x65B0;&#x629B;&#x51FA;&#x8BE5;&#x5F02;&#x5E38;&#x3002;&#x7531;&#x4E8E;finally&#x4EE3;&#x7801;&#x5757;&#x6709;&#x4E2A;return&#x8BED;&#x53E5;&#xFF0C;&#x5728;&#x91CD;&#x65B0;&#x629B;&#x51FA;&#x524D;&#x5C31;&#x8FD4;&#x56DE;&#x4E86;&#x3002;</p><p>&#x4F60;&#x53EF;&#x4EE5;&#x5229;&#x7528;&#x8FD9;&#x7BC7;&#x6587;&#x7AE0;&#x7684;&#x77E5;&#x8BC6;&#xFF0C;&#x5C31;&#x7740;javap&#x7684;&#x8F93;&#x51FA;&#xFF0C;&#x5206;&#x6790;&#x4E00;&#x4E0B;&#x5177;&#x4F53;&#x7684;&#x7A0B;&#x5E8F;&#x8DEF;&#x5F84;</p></blockquote><p>&#x6240;&#x4EE5;&#x5C31;&#x7740;JVM&#x5B57;&#x8282;&#x7801;&#x5177;&#x4F53;&#x5206;&#x6790;&#x4E86;&#x4E00;&#x4E0B;&#x4E24;&#x79CD;&#x7A0B;&#x5E8F;&#x8DEF;&#x5F84;:</p><ul><li>catch&#x5185;&#x629B;&#x51FA;&#x5F02;&#x5E38;, finally&#x5185;&#x5B58;&#x5728;return</li><li>catch&#x5185;&#x629B;&#x51FA;&#x5F02;&#x5E38;, finally&#x5185;&#x4E0D;&#x5B58;&#x5728;return</li></ul><a id="more"></a><h3 id="finally&#x5185;&#x4E0D;&#x5B58;&#x5728;return"><a href="#finally&#x5185;&#x4E0D;&#x5B58;&#x5728;return" class="headerlink" title="finally&#x5185;&#x4E0D;&#x5B58;&#x5728;return"></a>finally&#x5185;&#x4E0D;&#x5B58;&#x5728;return</h3><p>&#x5148;&#x770B;&#x4E0B;&#x6B63;&#x5E38;&#x60C5;&#x51B5;&#xFF0C;&#x5373;&#xFF1A;finally&#x5185;&#x4E0D;&#x5B58;&#x5728;return&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ExceptionTest</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>{</span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(<span class="string">&quot;runtime exception&quot;</span>);</span><br><span class="line">        } <span class="keyword">catch</span> (Exception e) {</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> Exception(<span class="string">&quot;inner exception&quot;</span>);</span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            System.out.println(<span class="string">&quot;finally&quot;</span>);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x901A;&#x8FC7;<code>javap</code>&#x83B7;&#x5F97;&#x7684;&#x5B57;&#x8282;&#x7801;&#x5185;&#x5BB9;&#xFF1A;<br></p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line">&quot;C:\Program Files\Java\jdk1.8.0_181\bin\javap.exe&quot; -l -c com.whatakitty.learn.ExceptionTest</span><br><span class="line">Compiled from &quot;ExceptionTest.java&quot;</span><br><span class="line">public class com.whatakitty.learn.ExceptionTest {</span><br><span class="line">  public com.whatakitty.learn.ExceptionTest();</span><br><span class="line">    Code:</span><br><span class="line">       0: aload_0</span><br><span class="line">       1: invokespecial #1                  // Method java/lang/Object.&quot;&lt;init&gt;&quot;:()V</span><br><span class="line">       4: return</span><br><span class="line">    LineNumberTable:</span><br><span class="line">      line 7: 0</span><br><span class="line">    LocalVariableTable:</span><br><span class="line">      Start  Length  Slot  Name   Signature</span><br><span class="line">          0       5     0  this   Lcom/whatakitty/learn/ExceptionTest;</span><br><span class="line"></span><br><span class="line">  # &#x4E3B;&#x8981;&#x67E5;&#x770B;&#x8FD9;&#x4E00;&#x5757;&#xFF0C;&#x8FD9;&#x91CC;&#x662F;main&#x65B9;&#x6CD5;&#x7684;&#x5B57;&#x8282;&#x7801;&#x5185;&#x5BB9;</span><br><span class="line">  public static void main(java.lang.String[]) throws java.lang.Exception;</span><br><span class="line">    Code:</span><br><span class="line">       0: new           #2                  // class java/lang/RuntimeException</span><br><span class="line">       3: dup</span><br><span class="line">       4: ldc           #3                  // String runtime exception</span><br><span class="line">       6: invokespecial #4                  // Method java/lang/RuntimeException.&quot;&lt;init&gt;&quot;:(Ljava/lang/String;)V</span><br><span class="line">       # &#x5728;&#x8FD9;&#x91CC;&#x629B;&#x51FA;RuntimeException&#x5F02;&#x5E38;&#xFF0C;&#x4ECE;&#x5F02;&#x5E38;&#x8868;&#x5185;&#x68C0;&#x67E5;to&#x548C;from&#x7684;&#x7684;&#x8303;&#x56F4;&#x4EE5;&#x53CA;&#x5BF9;&#x5E94;type&#x7684;&#x5339;&#x914D;&#xFF0C;&#x83B7;&#x5F97;&#x5230;&#x5F02;&#x5E38;&#x5904;&#x7406;&#x7684;&#x76EE;&#x6807;&#x4E3A;#10</span><br><span class="line">       9: athrow</span><br><span class="line">       # &#x629B;&#x51FA;&#x5F02;&#x5E38;&#x540E;&#x518D;&#x8FD9;&#x91CC;&#x5F00;&#x59CB;&#x5904;&#x7406;RuntimeException&#x5F02;&#x5E38;</span><br><span class="line">      10: astore_1</span><br><span class="line">      11: new           #5                  // class java/lang/Exception</span><br><span class="line">      14: dup</span><br><span class="line">      15: ldc           #6                  // String inner exception</span><br><span class="line">      17: invokespecial #7                  // Method java/lang/Exception.&quot;&lt;init&gt;&quot;:(Ljava/lang/String;)V</span><br><span class="line">      # &#x5728;&#x5904;&#x7406;&#x5F02;&#x5E38;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x53C8;&#x629B;&#x51FA;&#x4E00;&#x4E2A;&#x65B0;&#x7684;Exception&#x5F02;&#x5E38;&#xFF0C;&#x540C;&#x6837;&#x67E5;&#x627E;&#x5F02;&#x5E38;&#x8868;&#xFF0C;&#x83B7;&#x53D6;&#x5230;any&#x5F02;&#x5E38;&#x7684;&#x5339;&#x914D;&#xFF0C;&#x76EE;&#x6807;&#x4E3A;#21</span><br><span class="line">      20: athrow</span><br><span class="line">      # &#x5F00;&#x59CB;&#x5904;&#x7406;&#x672A;&#x6355;&#x83B7;&#x7684;&#x5F02;&#x5E38;Exception</span><br><span class="line">      21: astore_2</span><br><span class="line">      22: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">      25: ldc           #9                  // String finally</span><br><span class="line">      27: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">      30: aload_2</span><br><span class="line">      # &#x76F4;&#x63A5;&#x5C06;&#x672A;&#x6355;&#x83B7;&#x5F02;&#x5E38;&#x629B;&#x51FA;&#xFF0C;JVM&#x4F1A;&#x5728;&#x6267;&#x884C;&#x5B8C;&#x6574;&#x4E2A;&#x65B9;&#x6CD5;&#x540E;&#xFF0C;&#x5F39;&#x51FA;&#x6808;&#x5E27;&#xFF0C;&#x7136;&#x540E;&#x4F1A;&#x5904;&#x7406;&#x65B0;&#x7684;&#x9876;&#x5C42;&#x6808;&#x5E27;&#x3002;&#x8FD9;&#x91CC;&#x7684;&#x8BDD;&#xFF0C;&#x7531;&#x4E8E;&#x65E0;&#x65B0;&#x7684;&#x6808;&#x5E27;&#xFF0C;&#x7A0B;&#x5E8F;&#x76F4;&#x63A5;&#x7ED3;&#x675F;</span><br><span class="line">      31: athrow</span><br><span class="line">    # &#x5F02;&#x5E38;&#x8868;&#xFF0C;&#x6240;&#x6709;&#x7684;&#x6355;&#x83B7;&#x5F02;&#x5E38;&#x90FD;&#x4F1A;&#x5728;&#x8FD9;&#x91CC;&#x8BB0;&#x5F55;</span><br><span class="line">    Exception table:</span><br><span class="line">       from    to  target type</span><br><span class="line">           0    10    10   Class java/lang/Exception</span><br><span class="line">           0    22    21   any</span><br><span class="line">    LineNumberTable:</span><br><span class="line">      line 11: 0</span><br><span class="line">      line 12: 10</span><br><span class="line">      line 13: 11</span><br><span class="line">      line 15: 21</span><br><span class="line">      line 17: 30</span><br><span class="line">    LocalVariableTable:</span><br><span class="line">      Start  Length  Slot  Name   Signature</span><br><span class="line">         11      10     1     e   Ljava/lang/Exception;</span><br><span class="line">          0      32     0  args   [Ljava/lang/String;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><h3 id="finally&#x5185;&#x5B58;&#x5728;return"><a href="#finally&#x5185;&#x5B58;&#x5728;return" class="headerlink" title="finally&#x5185;&#x5B58;&#x5728;return"></a>finally&#x5185;&#x5B58;&#x5728;return</h3><p>&#x67E5;&#x770B;&#x4E86;&#x4E0D;&#x5B58;&#x5728;return&#x7684;&#x6B63;&#x5E38;&#x60C5;&#x51B5;&#xFF0C;&#x73B0;&#x5728;&#x770B;&#x4E00;&#x4E0B;&#x5982;&#x679C;&#x5728;finally&#x5185;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;return&#xFF0C;&#x5B57;&#x8282;&#x7801;&#x4F1A;&#x6709;&#x4EC0;&#x4E48;&#x53D8;&#x5316;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ExceptionTest</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>{</span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(<span class="string">&quot;runtime exception&quot;</span>);</span><br><span class="line">        } <span class="keyword">catch</span> (Exception e) {</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> Exception(<span class="string">&quot;inner exception&quot;</span>);</span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x901A;&#x8FC7;<code>javap</code>&#x83B7;&#x53D6;&#x7684;&#x5B57;&#x8282;&#x7801;&#xFF1A;<br></p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line">&quot;C:\Program Files\Java\jdk1.8.0_181\bin\javap.exe&quot; -l -c com.whatakitty.learn.ExceptionTest</span><br><span class="line">Compiled from &quot;ExceptionTest.java&quot;</span><br><span class="line">public class com.whatakitty.learn.ExceptionTest {</span><br><span class="line">  public com.whatakitty.learn.ExceptionTest();</span><br><span class="line">    Code:</span><br><span class="line">       0: aload_0</span><br><span class="line">       1: invokespecial #1                  // Method java/lang/Object.&quot;&lt;init&gt;&quot;:()V</span><br><span class="line">       4: return</span><br><span class="line">    LineNumberTable:</span><br><span class="line">      line 7: 0</span><br><span class="line">    LocalVariableTable:</span><br><span class="line">      Start  Length  Slot  Name   Signature</span><br><span class="line">          0       5     0  this   Lcom/whatakitty/learn/ExceptionTest;</span><br><span class="line"></span><br><span class="line">  public static void main(java.lang.String[]) throws java.lang.Exception;</span><br><span class="line">    Code:</span><br><span class="line">       0: new           #2                  // class java/lang/RuntimeException</span><br><span class="line">       3: dup</span><br><span class="line">       4: ldc           #3                  // String runtime exception</span><br><span class="line">       6: invokespecial #4                  // Method java/lang/RuntimeException.&quot;&lt;init&gt;&quot;:(Ljava/lang/String;)V</span><br><span class="line">       9: athrow</span><br><span class="line">      10: astore_1</span><br><span class="line">      11: new           #5                  // class java/lang/Exception</span><br><span class="line">      14: dup</span><br><span class="line">      15: ldc           #6                  // String inner exception</span><br><span class="line">      17: invokespecial #7                  // Method java/lang/Exception.&quot;&lt;init&gt;&quot;:(Ljava/lang/String;)V</span><br><span class="line">      # &#x622A;&#x6B62;&#x5230;&#x83B7;&#x53D6;&#x5F02;&#x5E38;&#x5E76;&#x629B;&#x51FA;&#x65B0;&#x7684;Exception&#x5F02;&#x5E38;&#x4E3A;&#x6B62;&#xFF0C;&#x4E0E;&#x524D;&#x8005;&#x7684;&#x6D41;&#x7A0B;&#x4FDD;&#x6301;&#x4E00;&#x81F4;&#x3002;</span><br><span class="line">      20: athrow</span><br><span class="line">      # &#x6839;&#x636E;&#x5F02;&#x5E38;&#x8868;&#x5B9A;&#x4F4D;&#x5E76;&#x83B7;&#x53D6;&#x76EE;&#x6807;#21&#x540E;&#x5F00;&#x59CB;&#x6267;&#x884C;finally&#x5757;&#x7684;&#x4EE3;&#x7801;</span><br><span class="line">      21: astore_2</span><br><span class="line">      # &#x7531;&#x4E8E;&#x5728;finally&#x5757;&#x5185;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x4E86;return&#xFF0C;&#x5E76;&#x4E0D;&#x4F1A;&#x518D;&#x6267;&#x884C;athrow&#x7684;&#x5B57;&#x8282;&#x7801;&#x6307;&#x4EE4;&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x8BF4;&#xFF1A;</span><br><span class="line">      # &#x5185;&#x90E8;&#x629B;&#x51FA;&#x7684;Exception&#x5F02;&#x5E38;&#xFF0C;&#x5DF2;&#x7ECF;&#x88AB;JVM&#x5FFD;&#x7565;</span><br><span class="line">      22: return</span><br><span class="line">    Exception table:</span><br><span class="line">       from    to  target type</span><br><span class="line">           0    10    10   Class java/lang/Exception</span><br><span class="line">           0    22    21   any</span><br><span class="line">    LineNumberTable:</span><br><span class="line">      line 11: 0</span><br><span class="line">      line 12: 10</span><br><span class="line">      line 13: 11</span><br><span class="line">      line 15: 21</span><br><span class="line">    LocalVariableTable:</span><br><span class="line">      Start  Length  Slot  Name   Signature</span><br><span class="line">         11      10     1     e   Ljava/lang/Exception;</span><br><span class="line">          0      23     0  args   [Ljava/lang/String;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><h3 id="&#x603B;&#x7ED3;"><a href="#&#x603B;&#x7ED3;" class="headerlink" title="&#x603B;&#x7ED3;"></a>&#x603B;&#x7ED3;</h3><p>&#x6309;&#x7167;&#x6B63;&#x5E38;&#x7684;&#x987A;&#x5E8F;&#x903B;&#x8F91;&#xFF0C;&#x5982;&#x679C;&#x51FA;&#x73B0;&#x672A;&#x6355;&#x83B7;&#x5F02;&#x5E38;&#xFF0C;&#x5219;&#x4F1A;&#x5728;finally&#x540E;&#x6267;&#x884C;&#x5B8C;&#x6210;&#x540E;&#x629B;&#x51FA;&#x8FD9;&#x4E2A;&#x5F02;&#x5E38;&#x3002;&#x4F46;&#x662F;&#xFF0C;&#x5982;&#x679C;&#x5728;finally&#x5757;&#x5185;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#xFF0C;&#x5219;&#x7A0B;&#x5E8F;&#x65E0;&#x6CD5;&#x6267;&#x884C;&#x5230;&#x629B;&#x51FA;&#x5F02;&#x5E38;&#x8FD9;&#x6B65;&#x64CD;&#x4F5C;&#x5C31;&#x5DF2;&#x7ECF;&#x88AB;&#x8FD4;&#x56DE;&#x4E86;&#x3002;</p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;刚看了极客时间关于JVM异常的相关信息，然后在评论里看到这么一条：&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;如果finally有return语句，catch内throw的异常会被忽略，这个从jvm层面怎么解释呢？&lt;br&gt;2018-09-02&lt;br&gt; 作者回复&lt;br&gt;catch里抛的异常会被finally捕获了，再执行完finally代码后重新抛出该异常。由于finally代码块有个return语句，在重新抛出前就返回了。&lt;/p&gt;&lt;p&gt;你可以利用这篇文章的知识，就着javap的输出，分析一下具体的程序路径&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;所以就着JVM字节码具体分析了一下两种程序路径:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;catch内抛出异常, finally内存在return&lt;/li&gt;&lt;li&gt;catch内抛出异常, finally内不存在return&lt;/li&gt;&lt;/ul&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="JVM" scheme="https://xuqiang.me/categories/Java/JVM/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="jvm" scheme="https://xuqiang.me/tags/jvm/"/>
    
      <category term="bytecode" scheme="https://xuqiang.me/tags/bytecode/"/>
    
  </entry>
  
  <entry>
    <title>Spring @Bean解析分析过程</title>
    <link href="https://xuqiang.me/Spring-Bean%E8%A7%A3%E6%9E%90%E5%88%86%E6%9E%90%E8%BF%87%E7%A8%8B.html"/>
    <id>https://xuqiang.me/Spring-Bean解析分析过程.html</id>
    <published>2018-08-23T16:35:49.000Z</published>
    <updated>2018-08-23T16:43:09.990Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x524D;&#x63D0;"><a href="#&#x524D;&#x63D0;" class="headerlink" title="&#x524D;&#x63D0;"></a>&#x524D;&#x63D0;</h3><ul><li>Spring 5</li><li>&#x57FA;&#x4E8E;Java Configuration&#x914D;&#x7F6E;&#xFF0C;&#x800C;&#x975E;XML&#x914D;&#x7F6E;</li><li>&#x975E;Web&#x73AF;&#x5883;</li></ul><h3 id="Bean&#x7684;&#x5904;&#x7406;"><a href="#Bean&#x7684;&#x5904;&#x7406;" class="headerlink" title="@Bean&#x7684;&#x5904;&#x7406;"></a>@Bean&#x7684;&#x5904;&#x7406;</h3><p>&#x4E0E;AOP&#x6784;&#x9020;&#x5668;&#x7684;&#x521B;&#x5EFA;&#x8FC7;&#x7A0B;&#x7C7B;&#x4F3C;&#xFF08;&#x5177;&#x4F53;&#x7684;&#x53EF;&#x4EE5;&#x67E5;&#x770B;&#x8FD9;&#x7BC7;&#x6587;&#x7AE0;&#xFF1A;<a href="https://xuqiang.me/&#x591A;&#x4E2A;AspectJ&#x5BF9;&#x540C;&#x4E00;&#x4E2A;&#x5BF9;&#x8C61;&#x64CD;&#x4F5C;&#x4EA7;&#x751F;&#x7684;&#x5B9E;&#x9645;&#x6548;&#x679C;&#x4EE5;&#x53CA;&#x987A;&#x5E8F;&#x60C5;&#x51B5;.html">&#x591A;&#x4E2A;AspectJ&#x5BF9;&#x540C;&#x4E00;&#x4E2A;&#x5BF9;&#x8C61;&#x64CD;&#x4F5C;&#x4EA7;&#x751F;&#x7684;&#x5B9E;&#x9645;&#x6548;&#x679C;&#x4EE5;&#x53CA;&#x987A;&#x5E8F;&#x60C5;&#x51B5;</a>&#xFF09;,<code>@Bean</code>&#x7684;&#x5904;&#x7406;&#x4E5F;&#x662F;&#x5728;<code>ConfigurationClassParser</code>&#x7C7B;&#x7684;<code>doProcessConfigurationClass</code>&#x65B9;&#x6CD5;&#x5185;&#x505A;&#x7684;&#x5904;&#x7406;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Process individual @Bean methods</span></span><br><span class="line">Set&lt;MethodMetadata&gt; beanMethods = retrieveBeanMethodMetadata(sourceClass);</span><br><span class="line"><span class="keyword">for</span> (MethodMetadata methodMetadata : beanMethods) {</span><br><span class="line">  configClass.addBeanMethod(<span class="keyword">new</span> BeanMethod(methodMetadata, configClass));</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x4E4B;&#x540E;&#x5728;<code>ConfigurationClassPostProcessor</code>&#x7C7B;&#x7684;<code>processConfigBeanDefinitions</code>&#x65B9;&#x6CD5;&#x5185;&#x89E3;&#x6790;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Read the model and create bean definitions based on its content</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">this</span>.reader == <span class="keyword">null</span>) {</span><br><span class="line">  <span class="keyword">this</span>.reader = <span class="keyword">new</span> ConfigurationClassBeanDefinitionReader(</span><br><span class="line">      registry, <span class="keyword">this</span>.sourceExtractor, <span class="keyword">this</span>.resourceLoader, <span class="keyword">this</span>.environment,</span><br><span class="line">      <span class="keyword">this</span>.importBeanNameGenerator, parser.getImportRegistry());</span><br><span class="line">}</span><br><span class="line"><span class="keyword">this</span>.reader.loadBeanDefinitions(configClasses);</span><br></pre></td></tr></tbody></table></figure><p></p><a id="more"></a><p><code>retrieveBeanMethodMetadata</code>&#x65B9;&#x6CD5;&#xFF0C;&#x4E3B;&#x8981;&#x662F;&#x4E3A;&#x4E86;&#x83B7;&#x53D6;<code>@Bean</code>&#x6CE8;&#x89E3;&#x7684;&#x65B9;&#x6CD5;&#x7684;&#x76F8;&#x5173;&#x5143;&#x6570;&#x636E;&#xFF0C;&#x6BD4;&#x5982;&#x65B9;&#x6CD5;&#x540D;&#x3001;&#x6240;&#x5728;&#x7C7B;&#x5168;&#x540D;&#x3001;&#x8FD4;&#x56DE;&#x7C7B;&#x578B;&#x3001;&#x662F;&#x5426;&#x9759;&#x6001;&#x3001;&#x662F;&#x5426;&#x4E0D;&#x53EF;&#x8986;&#x76D6;&#x7B49;&#x7B49;&#x4FE1;&#x606F;&#x3002;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> Set&lt;MethodMetadata&gt; <span class="title">retrieveBeanMethodMetadata</span><span class="params">(SourceClass sourceClass)</span> </span>{</span><br><span class="line">  <span class="comment">// &#x83B7;&#x53D6;&#x7C7B;&#x7684;&#x5143;&#x6570;&#x636E;</span></span><br><span class="line">  AnnotationMetadata original = sourceClass.getMetadata();</span><br><span class="line">  <span class="comment">// &#x4ECE;&#x5143;&#x6570;&#x636E;&#x5185;&#x83B7;&#x53D6;&#x6CE8;&#x89E3;&#x6709;@Bean&#x7684;&#x65B9;&#x6CD5;&#x96C6;&#x5408;</span></span><br><span class="line">  Set&lt;MethodMetadata&gt; beanMethods = original.getAnnotatedMethods(Bean.class.getName());</span><br><span class="line">  <span class="comment">// &#x5224;&#x65AD;&#x65B9;&#x6CD5;&#x96C6;&#x5408;&#x662F;&#x5426;&#x8D85;&#x8FC7;&#x4E24;&#x4E2A;&#xFF0C;&#x5E76;&#x4E14;&#x7C7B;&#x7684;&#x5143;&#x6570;&#x636E;&#x662F;StandardAnnotationMetadata&#x5B9E;&#x4F8B;&#xFF0C;&#x5219;&#x4ECE;ASM&#x5185;&#x83B7;&#x53D6;&#x58F0;&#x660E;&#x7684;&#x65B9;&#x6CD5;&#x987A;&#x5E8F;</span></span><br><span class="line">  <span class="keyword">if</span> (beanMethods.size() &gt; <span class="number">1</span> &amp;&amp; original <span class="keyword">instanceof</span> StandardAnnotationMetadata) {</span><br><span class="line">    <span class="comment">// &#x5C1D;&#x8BD5;&#x901A;&#x8FC7;ASM&#x4ECE;&#x7C7B;&#x6587;&#x4EF6;&#x5224;&#x65AD;&#x65B9;&#x6CD5;&#x7684;&#x987A;&#x5E8F;...&#x56E0;&#x4E3A;&#xFF0C;JVM&#x7684;&#x6807;&#x51C6;&#x53CD;&#x5C04;&#x5E93;&#x83B7;&#x53D6;&#x7684;&#x65B9;&#x6CD5;&#x987A;&#x5E8F;&#x662F;&#x968F;&#x673A;&#x7684;&#xFF0C;&#x751A;&#x81F3;&#x6CE1;&#x5728;&#x76F8;&#x540C;JVM&#x7684;&#x4E0D;&#x540C;&#x5E94;&#x7528;&#x8FD4;&#x56DE;&#x7684;&#x987A;&#x5E8F;&#x4E5F;&#x4F1A;&#x4E0D;&#x4E00;&#x81F4;</span></span><br><span class="line">    <span class="keyword">try</span> {</span><br><span class="line">      AnnotationMetadata asm =</span><br><span class="line">          <span class="keyword">this</span>.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();</span><br><span class="line">      Set&lt;MethodMetadata&gt; asmMethods = asm.getAnnotatedMethods(Bean.class.getName());</span><br><span class="line">      <span class="keyword">if</span> (asmMethods.size() &gt;= beanMethods.size()) {</span><br><span class="line">        Set&lt;MethodMetadata&gt; selectedMethods = <span class="keyword">new</span> LinkedHashSet&lt;&gt;(asmMethods.size());</span><br><span class="line">        <span class="comment">// &#x505A;&#x4E86;&#x4E00;&#x904D;&#x8FC7;&#x6EE4;&#xFF0C;&#x5C06;&#x4E8C;&#x8FDB;&#x5236;class&#x6587;&#x4EF6;&#x7684;&#x65B9;&#x6CD5;&#x4E0E;JVM&#x53CD;&#x5C04;&#x7684;&#x65B9;&#x6CD5;&#x505A;&#x4E00;&#x6B21;&#x5BF9;&#x6BD4;&#xFF0C;&#x9632;&#x6B62;&#x5C06;&#x975E;&#x7F16;&#x7A0B;&#x65B9;&#x6CD5;&#x52A0;&#x5165;&#xFF0C;&#x4FDD;&#x6301;&#x4E0E;JVM&#x53CD;&#x5C04;&#x83B7;&#x53D6;&#x65B9;&#x6CD5;&#x4E00;&#x81F4;&#xFF0C;&#x9664;&#x4E86;&#x987A;&#x5E8F;&#x3002;</span></span><br><span class="line">        <span class="keyword">for</span> (MethodMetadata asmMethod : asmMethods) {</span><br><span class="line">          <span class="keyword">for</span> (MethodMetadata beanMethod : beanMethods) {</span><br><span class="line">            <span class="keyword">if</span> (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {</span><br><span class="line">              selectedMethods.add(beanMethod);</span><br><span class="line">              <span class="keyword">break</span>;</span><br><span class="line">            }</span><br><span class="line">          }</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">if</span> (selectedMethods.size() == beanMethods.size()) {</span><br><span class="line">          <span class="comment">// All reflection-detected methods found in ASM method set -&gt; proceed</span></span><br><span class="line">          beanMethods = selectedMethods;</span><br><span class="line">        }</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">catch</span> (IOException ex) {</span><br><span class="line">      logger.debug(<span class="string">&quot;Failed to read class file via ASM for determining @Bean method order&quot;</span>, ex);</span><br><span class="line">      <span class="comment">// No worries, let&apos;s continue with the reflection metadata we started with...</span></span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">return</span> beanMethods;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x5728;<code>loadBeanDefinitions</code>&#x65B9;&#x6CD5;&#x5185;&#xFF0C;&#x8C03;&#x7528;&#x4E86;<code>loadBeanDefinitionsForConfigurationClass</code>&#x6765;&#x6CE8;&#x518C;Config Bean&#x672C;&#x8EAB;&#x3001;&#x5185;&#x90E8;&#x58F0;&#x660E;&#x7684;<code>@Bean</code>&#x65B9;&#x6CD5;&#x3001;<code>@Import</code>&#x548C;<code>@ImportResource</code>&#x76F8;&#x5173;&#x7684;Bean&#x4FE1;&#x606F;&#x3002;&#x8FD9;&#x91CC;&#x5177;&#x4F53;&#x67E5;&#x770B;&#x6CE8;&#x518C;<code>@Bean</code>&#x7684;&#x8FC7;&#x7A0B;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5FAA;&#x73AF;&#x6240;&#x6709;&#x6CE8;&#x89E3;&#x6709;@Bean&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x5E76;&#x8C03;&#x7528;loadBeanDefinitionsForBeanMethod&#x65B9;&#x6CD5;&#x6CE8;&#x518C;</span></span><br><span class="line"><span class="keyword">for</span> (BeanMethod beanMethod : configClass.getBeanMethods()) {</span><br><span class="line">  loadBeanDefinitionsForBeanMethod(beanMethod);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p><code>loadBeanDefinitionsForBeanMethod</code>&#x65B9;&#x6CD5;&#x4E3B;&#x8981;&#x662F;&#x505A;&#x4E86;&#x522B;&#x540D;&#x6CE8;&#x518C;&#xFF0C;&#x6CE8;&#x89E3;&#x58F0;&#x660E;&#x7684;&#x7C7B;&#x5B9A;&#x4E49;&#x6CE8;&#x518C;&#x4EE5;&#x53CA;<code>@Scope</code>&#x6CE8;&#x89E3;&#x7684;&#x4EE3;&#x7406;&#x7C7B;&#x8986;&#x76D6;&#x7684;&#x5DE5;&#x4F5C;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">loadBeanDefinitionsForBeanMethod</span><span class="params">(BeanMethod beanMethod)</span> </span>{</span><br><span class="line">  <span class="comment">// &#x83B7;&#x53D6;&#x914D;&#x7F6E;&#x7C7B;&#x4EE5;&#x53CA;&#x6CE8;&#x89E3;&#x65B9;&#x6CD5;&#x7684;&#x76F8;&#x5173;&#x4FE1;&#x606F;</span></span><br><span class="line">  ConfigurationClass configClass = beanMethod.getConfigurationClass();</span><br><span class="line">  MethodMetadata metadata = beanMethod.getMetadata();</span><br><span class="line">  String methodName = metadata.getMethodName();</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x5224;&#x65AD;&#x662F;&#x5426;&#x9700;&#x8981;&#x8DF3;&#x8FC7;&#x8FD9;&#x4E2A;&#x7C7B;</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">this</span>.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {</span><br><span class="line">    configClass.skippedBeanMethods.add(methodName);</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  }</span><br><span class="line">  <span class="comment">// &#x5982;&#x679C;&#x8FD9;&#x4E2A;&#x7C7B;&#x88AB;&#x8DF3;&#x8FC7;&#xFF0C;&#x5219;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;</span></span><br><span class="line">  <span class="keyword">if</span> (configClass.skippedBeanMethods.contains(methodName)) {</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x63D0;&#x53D6;@Bean&#x6CE8;&#x89E3;&#x7684;&#x5C5E;&#x6027;</span></span><br><span class="line">  AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);</span><br><span class="line">  <span class="comment">// &#x4E0D;&#x5B58;&#x5728;@Bean&#xFF0C;&#x5219;&#x629B;&#x51FA;&#x5F02;&#x5E38;</span></span><br><span class="line">  Assert.state(bean != <span class="keyword">null</span>, <span class="string">&quot;No @Bean annotation attributes&quot;</span>);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x83B7;&#x53D6;@Bean&#x6CE8;&#x518C;&#x7684;&#x522B;&#x540D;</span></span><br><span class="line">  List&lt;String&gt; names = <span class="keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(bean.getStringArray(<span class="string">&quot;name&quot;</span>)));</span><br><span class="line">  String beanName = (!names.isEmpty() ? names.remove(<span class="number">0</span>) : methodName);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x6CE8;&#x518C;&#x6240;&#x6709;&#x7684;&#x522B;&#x540D;</span></span><br><span class="line">  <span class="keyword">for</span> (String alias : names) {</span><br><span class="line">    <span class="keyword">this</span>.registry.registerAlias(beanName, alias);</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x662F;&#x5426;&#x5141;&#x8BB8;&#x8986;&#x76D6;&#x5DF2;&#x5B58;&#x5728;&#x7684;&#x5B9A;&#x4E49;&#xFF08;&#x5224;&#x65AD;&#x4F9D;&#x636E;&#x6765;&#x81EA;isOverriddenByExistingDefinition&#x65B9;&#x6CD5;&#xFF0C;&#x8FD9;&#x91CC;&#x4E0D;&#x505A;&#x5C55;&#x5F00;&#xFF09;</span></span><br><span class="line">  <span class="keyword">if</span> (isOverriddenByExistingDefinition(beanMethod, beanName)) {</span><br><span class="line">    <span class="keyword">if</span> (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {</span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),</span><br><span class="line">          beanName, <span class="string">&quot;Bean name derived from @Bean method &apos;&quot;</span> + beanMethod.getMetadata().getMethodName() +</span><br><span class="line">          <span class="string">&quot;&apos; clashes with bean name for containing configuration class; please make those names unique!&quot;</span>);</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  ConfigurationClassBeanDefinition beanDef = <span class="keyword">new</span> ConfigurationClassBeanDefinition(configClass, metadata);</span><br><span class="line">  beanDef.setResource(configClass.getResource());</span><br><span class="line">  beanDef.setSource(<span class="keyword">this</span>.sourceExtractor.extractSource(metadata, configClass.getResource()));</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (metadata.isStatic()) {</span><br><span class="line">    <span class="comment">// static @Bean method</span></span><br><span class="line">    beanDef.setBeanClassName(configClass.getMetadata().getClassName());</span><br><span class="line">    beanDef.setFactoryMethodName(methodName);</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">else</span> {</span><br><span class="line">    <span class="comment">// instance @Bean method</span></span><br><span class="line">    beanDef.setFactoryBeanName(configClass.getBeanName());</span><br><span class="line">    beanDef.setUniqueFactoryMethodName(methodName);</span><br><span class="line">  }</span><br><span class="line">  beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);</span><br><span class="line">  beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);</span><br><span class="line"></span><br><span class="line">  AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);</span><br><span class="line"></span><br><span class="line">  Autowire autowire = bean.getEnum(<span class="string">&quot;autowire&quot;</span>);</span><br><span class="line">  <span class="keyword">if</span> (autowire.isAutowire()) {</span><br><span class="line">    beanDef.setAutowireMode(autowire.value());</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  String initMethodName = bean.getString(<span class="string">&quot;initMethod&quot;</span>);</span><br><span class="line">  <span class="keyword">if</span> (StringUtils.hasText(initMethodName)) {</span><br><span class="line">    beanDef.setInitMethodName(initMethodName);</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  String destroyMethodName = bean.getString(<span class="string">&quot;destroyMethod&quot;</span>);</span><br><span class="line">  beanDef.setDestroyMethodName(destroyMethodName);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Scope&#x7684;&#x4EE3;&#x7406;&#x4FE1;&#x606F;&#x83B7;&#x53D6;</span></span><br><span class="line">  ScopedProxyMode proxyMode = ScopedProxyMode.NO;</span><br><span class="line">  AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);</span><br><span class="line">  <span class="keyword">if</span> (attributes != <span class="keyword">null</span>) {</span><br><span class="line">    beanDef.setScope(attributes.getString(<span class="string">&quot;value&quot;</span>));</span><br><span class="line">    proxyMode = attributes.getEnum(<span class="string">&quot;proxyMode&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (proxyMode == ScopedProxyMode.DEFAULT) {</span><br><span class="line">      proxyMode = ScopedProxyMode.NO;</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x5982;&#x679C;&#x5B58;&#x5728;Scope&#x4EE3;&#x7406;&#xFF0C;&#x5219;&#x4F7F;&#x7528;&#x4EE3;&#x7406;&#x7C7B;&#x5B9A;&#x4E49;&#x8986;&#x76D6;&#x539F;&#x6709;&#x7684;&#x7C7B;&#x5B9A;&#x4E49;</span></span><br><span class="line">  BeanDefinition beanDefToRegister = beanDef;</span><br><span class="line">  <span class="keyword">if</span> (proxyMode != ScopedProxyMode.NO) {</span><br><span class="line">    BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(</span><br><span class="line">        <span class="keyword">new</span> BeanDefinitionHolder(beanDef, beanName), <span class="keyword">this</span>.registry,</span><br><span class="line">        proxyMode == ScopedProxyMode.TARGET_CLASS);</span><br><span class="line">    beanDefToRegister = <span class="keyword">new</span> ConfigurationClassBeanDefinition(</span><br><span class="line">        (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (logger.isDebugEnabled()) {</span><br><span class="line">    logger.debug(String.format(<span class="string">&quot;Registering bean definition for @Bean method %s.%s()&quot;</span>,</span><br><span class="line">        configClass.getMetadata().getClassName(), beanName));</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x6CE8;&#x518C;&#x7C7B;&#x5B9A;&#x4E49;</span></span><br><span class="line">  <span class="keyword">this</span>.registry.registerBeanDefinition(beanName, beanDefToRegister);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x4E4B;&#x540E;&#x901A;&#x8FC7;Bean&#x5DE5;&#x5382;&#xFF0C;&#x8C03;&#x7528;<code>preInstantiateSingletons</code>&#x65B9;&#x6CD5;&#xFF0C;&#x4E0E;&#x521D;&#x59CB;&#x5316;Bean&#x7684;&#x5355;&#x4F8B;&#x3002;&#x5728;&#x8FD9;&#x4E2A;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x540C;&#x6837;&#x5C06;<code>@Bean</code>&#x6807;&#x6CE8;&#x7684;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x521D;&#x59CB;&#x5316;&#x4E86;&#x3002;&#x4E0E;&#x5176;&#x4ED6;&#x7C7B;&#x7684;&#x521D;&#x59CB;&#x5316;&#x4E0D;&#x540C;&#x7684;&#x662F;&#xFF0C;&#x6807;&#x6CE8;&#x6709;<code>@Bean</code>&#x7684;&#x7C7B;&#x6784;&#x9020;&#x65B9;&#x6CD5;&#x7684;&#x521D;&#x59CB;&#x5316;&#xFF0C;&#x662F;&#x901A;&#x8FC7;<code>factoryMethodName</code>&#x6765;&#x8FDB;&#x884C;&#x7684;(&#x5177;&#x4F53;&#x67E5;&#x770B;&#x7684;<code>AbstractAutowireCapableBeanFactory</code>&#x7C7B;&#x7684;<code>createBeanInstance</code>&#x65B9;&#x6CD5;)&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5224;&#x65AD;&#x662F;&#x5426;&#x5B58;&#x5728;factoryMethodName</span></span><br><span class="line"><span class="keyword">if</span> (mbd.getFactoryMethodName() != <span class="keyword">null</span>)  {</span><br><span class="line">  <span class="comment">// &#x5B58;&#x5728;&#x7684;&#x8BDD;&#xFF0C;&#x5219;&#x901A;&#x8FC7;factoryMethodName&#x6765;&#x8FDB;&#x884C;&#x521D;&#x59CB;&#x5316;</span></span><br><span class="line">  <span class="keyword">return</span> instantiateUsingFactoryMethod(beanName, mbd, args);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x901A;&#x8FC7;<code>factoryMethodName</code>&#x521D;&#x59CB;&#x5316;Bean</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">protected</span> BeanWrapper <span class="title">instantiateUsingFactoryMethod</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">    String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs)</span> </span>{</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> ConstructorResolver(<span class="keyword">this</span>).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5177;&#x4F53;&#x7684;&#x521D;&#x59CB;&#x5316;&#x8FC7;&#x7A0B;&#x5982;&#x4E0B;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> BeanWrapper <span class="title">instantiateUsingFactoryMethod</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"><span class="keyword">final</span> String beanName, <span class="keyword">final</span> RootBeanDefinition mbd, @Nullable <span class="keyword">final</span> Object[] explicitArgs)</span> </span>{</span><br><span class="line"></span><br><span class="line">  BeanWrapperImpl bw = <span class="keyword">new</span> BeanWrapperImpl();</span><br><span class="line">  <span class="keyword">this</span>.beanFactory.initBeanWrapper(bw);</span><br><span class="line"></span><br><span class="line">  Object factoryBean;</span><br><span class="line">  Class&lt;?&gt; factoryClass;</span><br><span class="line">  <span class="keyword">boolean</span> isStatic;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x83B7;&#x53D6;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x6240;&#x5728;&#x914D;&#x7F6E;&#x7C7B;&#x540D;&#x79F0;</span></span><br><span class="line">  String factoryBeanName = mbd.getFactoryBeanName();</span><br><span class="line">  <span class="keyword">if</span> (factoryBeanName != <span class="keyword">null</span>) {</span><br><span class="line">    <span class="comment">// &#x5B58;&#x5728;&#x914D;&#x7F6E;&#x7C7B;&#x540D;&#x79F0;&#xFF0C;&#x5219;@Bean&#x662F;&#x88AB;&#x6807;&#x8BB0;&#x5728;&#x5B9E;&#x4F8B;&#x65B9;&#x6CD5;&#x4E0A;</span></span><br><span class="line">    <span class="comment">// &#x914D;&#x7F6E;&#x7C7B;&#x4E0E;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x6784;&#x5EFA;&#x7684;&#x76EE;&#x6807;&#x7C7B;&#x4E00;&#x81F4;&#xFF0C;&#x629B;&#x51FA;&#x5F02;&#x5E38;</span></span><br><span class="line">    <span class="keyword">if</span> (factoryBeanName.equals(beanName)) {</span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,</span><br><span class="line">          <span class="string">&quot;factory-bean reference points back to the same bean definition&quot;</span>);</span><br><span class="line">    }</span><br><span class="line">    factoryBean = <span class="keyword">this</span>.beanFactory.getBean(factoryBeanName);</span><br><span class="line">    <span class="comment">// &#x5B58;&#x5728;&#x8BE5;&#x6784;&#x5EFA;&#x76EE;&#x6807;&#x7684;bean&#x540D;&#x79F0;&#x4E0E;&#x5BB9;&#x5668;&#x5185;&#x7684;&#x5176;&#x4ED6;Bean&#x5B9A;&#x4E49;&#x51B2;&#x7A81;&#xFF0C;&#x629B;&#x51FA;&#x5F02;&#x5E38;</span></span><br><span class="line">    <span class="keyword">if</span> (mbd.isSingleton() &amp;&amp; <span class="keyword">this</span>.beanFactory.containsSingleton(beanName)) {</span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> ImplicitlyAppearedSingletonException();</span><br><span class="line">    }</span><br><span class="line">    factoryClass = factoryBean.getClass();</span><br><span class="line">    isStatic = <span class="keyword">false</span>;</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">else</span> {</span><br><span class="line">    <span class="comment">// @Bean&#x6807;&#x6CE8;&#x5728;&#x9759;&#x6001;&#x65B9;&#x6CD5;&#x4E0A;</span></span><br><span class="line">    <span class="comment">// &#x4E0D;&#x5B58;&#x5728;&#x6784;&#x5EFA;&#x76EE;&#x6807;&#x7684;Class&#x7C7B;&#x578B;&#xFF0C;&#x5219;&#x629B;&#x51FA;&#x5F02;&#x5E38;&#x3002;&#x5373;&#xFF1A;&#x58F0;&#x660E;&#x7684;&#x7C7B;&#x5B9A;&#x4E49;&#x65E2;&#x4E0D;&#x662F;&#x4E00;&#x4E2A;Bean&#x7C7B;&#xFF0C;&#x4E5F;&#x4E0D;&#x662F;&#x4E00;&#x4E2A;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;</span></span><br><span class="line">    <span class="keyword">if</span> (!mbd.hasBeanClass()) {</span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,</span><br><span class="line">          <span class="string">&quot;bean definition declares neither a bean class nor a factory-bean reference&quot;</span>);</span><br><span class="line">    }</span><br><span class="line">    factoryBean = <span class="keyword">null</span>;</span><br><span class="line">    factoryClass = mbd.getBeanClass();</span><br><span class="line">    isStatic = <span class="keyword">true</span>;</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  Method factoryMethodToUse = <span class="keyword">null</span>;</span><br><span class="line">  ArgumentsHolder argsHolderToUse = <span class="keyword">null</span>;</span><br><span class="line">  Object[] argsToUse = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x5224;&#x65AD;&#x662F;&#x5426;&#x663E;&#x793A;&#x4F20;&#x5165;&#x53C2;&#x6570;</span></span><br><span class="line">  <span class="comment">// &#x5982;&#x679C;&#x4E0D;&#x662F;&#x663E;&#x793A;&#x4F20;&#x5165;&#x53C2;&#x6570;&#xFF0C;&#x5219;&#x6839;&#x636E;constructorArgumentsResolved&#x5224;&#x65AD;&#x662F;&#x5426;&#x9700;&#x8981;&#x89E3;&#x6790;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x7684;&#x53C2;&#x6570;</span></span><br><span class="line">  <span class="keyword">if</span> (explicitArgs != <span class="keyword">null</span>) {</span><br><span class="line">    argsToUse = explicitArgs;</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">else</span> {</span><br><span class="line">    Object[] argsToResolve = <span class="keyword">null</span>;</span><br><span class="line">    <span class="comment">// &#x4F7F;&#x7528;&#x9501;&#xFF0C;&#x4FDD;&#x8BC1;&#x8BFB;&#x53D6;&#x5230;&#x7684;resolvedConstructorOrFactoryMethod&#x3001;constructorArgumentsResolved&#x3001;resolvedConstructorArguments&#x4EE5;&#x53CA;preparedConstructorArguments&#x662F;&#x6B63;&#x786E;&#x7684;&#xFF0C;&#x9632;&#x6B62;&#x7EBF;&#x7A0B;&#x5728;&#x5176;&#x4ED6;&#x7EBF;&#x7A0B;&#x4FEE;&#x6539;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#x8BFB;&#x53D6;&#x9519;&#x8BEF;&#x7684;&#x6570;&#x636E;</span></span><br><span class="line">    <span class="comment">// &#x67E5;&#x770B;&#x662F;&#x5426;&#x5B58;&#x5728;&#x4E00;&#x4E2A;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x7684;&#x7F13;&#x5B58;&#xFF0C;&#x4E0D;&#x5B58;&#x5728;&#x7684;&#x8BDD;&#x901A;&#x8FC7;&#x53CD;&#x5C04;&#x91CD;&#x65B0;&#x67E5;&#x627E;&#x5339;&#x914D;&#xFF0C;&#x5E76;&#x5728;&#x67E5;&#x627E;&#x5B8C;&#x6210;&#x540E;&#xFF0C;&#x505A;storeCache&#x7684;&#x7F13;&#x5B58;&#x4F5C;&#x4E1A;</span></span><br><span class="line">    <span class="keyword">synchronized</span> (mbd.constructorArgumentLock) {</span><br><span class="line">      factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;</span><br><span class="line">      <span class="keyword">if</span> (factoryMethodToUse != <span class="keyword">null</span> &amp;&amp; mbd.constructorArgumentsResolved) {</span><br><span class="line">        <span class="comment">// &#x627E;&#x5230;&#x4E00;&#x4E2A;&#x7F13;&#x5B58;&#x7684;&#x6784;&#x9020;&#x65B9;&#x6CD5;&#xFF08;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x6216;&#x8005;&#x7C7B;&#x6784;&#x9020;&#x5668;&#xFF09;</span></span><br><span class="line">        argsToUse = mbd.resolvedConstructorArguments;</span><br><span class="line">        <span class="keyword">if</span> (argsToUse == <span class="keyword">null</span>) {</span><br><span class="line">          argsToResolve = mbd.preparedConstructorArguments;</span><br><span class="line">        }</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line">    <span class="comment">// &#x5BF9;&#x4E8E;&#x4F20;&#x5165;&#x7684;&#x53C2;&#x6570;&#x505A;&#x89E3;&#x6790;</span></span><br><span class="line">    <span class="keyword">if</span> (argsToResolve != <span class="keyword">null</span>) {</span><br><span class="line">      argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (factoryMethodToUse == <span class="keyword">null</span> || argsToUse == <span class="keyword">null</span>) {</span><br><span class="line">    <span class="comment">// &#x65E0;&#x6784;&#x9020;&#x65B9;&#x6CD5;&#xFF0C;&#x5219;&#x901A;&#x8FC7;&#x53CD;&#x5C04;&#x67E5;&#x627E;&#x5339;&#x914D;&#x7684;&#x65B9;&#x6CD5;</span></span><br><span class="line">    factoryClass = ClassUtils.getUserClass(factoryClass);</span><br><span class="line"></span><br><span class="line">    Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);</span><br><span class="line">    List&lt;Method&gt; candidateSet = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span> (Method candidate : rawCandidates) {</span><br><span class="line">      <span class="comment">// &#x5C06;&#x5339;&#x914D;&#x7684;&#x65B9;&#x6CD5;&#x653E;&#x5230;&#x5217;&#x8868;&#x5185;&#x7F13;&#x5B58;&#xFF08;&#x662F;&#x5426;&#x9759;&#x6001;&#x5E76;&#x4E14;&#x65B9;&#x6CD5;&#x540D;&#x662F;&#x5426;&#x4E00;&#x81F4;&#xFF09;</span></span><br><span class="line">      <span class="keyword">if</span> (Modifier.isStatic(candidate.getModifiers()) == isStatic &amp;&amp; mbd.isFactoryMethod(candidate)) {</span><br><span class="line">        candidateSet.add(candidate);</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line">    Method[] candidates = candidateSet.toArray(<span class="keyword">new</span> Method[<span class="number">0</span>]);</span><br><span class="line">    <span class="comment">// &#x6392;&#x5E8F;&#xFF08;&#x6309;&#x7167;&#x662F;&#x5426;&#x516C;&#x5F00;&#x65B9;&#x6CD5;&#xFF0C;&#x5E76;&#x4E14;&#x53C2;&#x6570;&#x4E2A;&#x6570;&#x6392;&#x5E8F;&#xFF09;</span></span><br><span class="line">    AutowireUtils.sortFactoryMethods(candidates);</span><br><span class="line"></span><br><span class="line">    ConstructorArgumentValues resolvedValues = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">boolean</span> autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);</span><br><span class="line">    <span class="keyword">int</span> minTypeDiffWeight = Integer.MAX_VALUE;</span><br><span class="line">    Set&lt;Method&gt; ambiguousFactoryMethods = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> minNrOfArgs;</span><br><span class="line">    <span class="keyword">if</span> (explicitArgs != <span class="keyword">null</span>) {</span><br><span class="line">      minNrOfArgs = explicitArgs.length;</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">else</span> {</span><br><span class="line">      <span class="comment">// &#x56E0;&#x4E3A;&#x6CA1;&#x6709;&#x901A;&#x8FC7;&#x7A0B;&#x5E8F;&#x6027;&#x4F20;&#x5165;&#x6784;&#x9020;&#x53C2;&#x6570;&#xFF0C;&#x6240;&#x4EE5;&#x9700;&#x8981;&#x624B;&#x52A8;&#x5224;&#x65AD;&#x5E76;&#x89E3;&#x6790;&#x8FD9;&#x4E9B;&#x53C2;&#x6570;</span></span><br><span class="line">      <span class="comment">// &#x5982;&#x679C;&#x5B58;&#x5728;&#x6784;&#x9020;&#x53C2;&#x6570;&#xFF0C;&#x5219;&#x89E3;&#x6790;&#x8FD9;&#x4E9B;&#x53C2;&#x6570;</span></span><br><span class="line">      <span class="keyword">if</span> (mbd.hasConstructorArgumentValues()) {</span><br><span class="line">        ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();</span><br><span class="line">        resolvedValues = <span class="keyword">new</span> ConstructorArgumentValues();</span><br><span class="line">        minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);</span><br><span class="line">      }</span><br><span class="line">      <span class="keyword">else</span> {</span><br><span class="line">        minNrOfArgs = <span class="number">0</span>;</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    LinkedList&lt;UnsatisfiedDependencyException&gt; causes = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x904D;&#x5386;&#x4E0E;&#x6784;&#x9020;&#x65B9;&#x6CD5;&#x540D;&#x5B57;&#x76F8;&#x540C;&#x7684;&#x6240;&#x6709;&#x65B9;&#x6CD5;</span></span><br><span class="line">    <span class="keyword">for</span> (Method candidate : candidates) {</span><br><span class="line">      <span class="comment">// &#x83B7;&#x53D6;&#x65B9;&#x6CD5;&#x7684;&#x53C2;&#x6570;&#x7C7B;&#x578B;&#x5217;&#x8868;</span></span><br><span class="line">      Class&lt;?&gt;[] paramTypes = candidate.getParameterTypes();</span><br><span class="line"></span><br><span class="line">      <span class="keyword">if</span> (paramTypes.length &gt;= minNrOfArgs) {</span><br><span class="line">        ArgumentsHolder argsHolder;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (explicitArgs != <span class="keyword">null</span>){</span><br><span class="line">          <span class="comment">// &#x5982;&#x679C;&#x662F;&#x663E;&#x5F0F;&#x58F0;&#x660E;&#x7684;&#x6784;&#x9020;&#x53C2;&#x6570;&#xFF0C;&#x5219;&#x53CD;&#x5C04;&#x83B7;&#x5F97;&#x7684;&#x6784;&#x9020;&#x65B9;&#x6CD5;&#x53C2;&#x6570;&#x7C7B;&#x578B;&#x957F;&#x5EA6;&#x4E0E;&#x663E;&#x793A;&#x53C2;&#x6570;&#x7684;&#x4E2A;&#x6570;&#x9700;&#x8981;&#x4FDD;&#x6301;&#x4E00;&#x81F4;</span></span><br><span class="line">          <span class="comment">// &#x5373;&#x8FD9;&#x4E9B;&#x53C2;&#x6570;&#x90FD;&#x662F;&#x5FC5;&#x8981;&#x6027;&#x53C2;&#x6570;</span></span><br><span class="line">          <span class="keyword">if</span> (paramTypes.length != explicitArgs.length) {</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">          }</span><br><span class="line">          argsHolder = <span class="keyword">new</span> ArgumentsHolder(explicitArgs);</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">else</span> {</span><br><span class="line">          <span class="comment">// &#x89E3;&#x6790;&#x6784;&#x9020;&#x53C2;&#x6570;&#xFF0C;&#x8FD9;&#x4E9B;&#x53C2;&#x6570;&#x53EF;&#x4EE5;&#x662F;&#x5FC5;&#x586B;&#x6216;&#x8005;&#x975E;&#x5FC5;&#x586B;</span></span><br><span class="line">          <span class="keyword">try</span> {</span><br><span class="line">            String[] paramNames = <span class="keyword">null</span>;</span><br><span class="line">            ParameterNameDiscoverer pnd = <span class="keyword">this</span>.beanFactory.getParameterNameDiscoverer();</span><br><span class="line">            <span class="keyword">if</span> (pnd != <span class="keyword">null</span>) {</span><br><span class="line">              paramNames = pnd.getParameterNames(candidate);</span><br><span class="line">            }</span><br><span class="line">            <span class="comment">// &#x6839;&#x636E;&#x4FE1;&#x606F;&#x521B;&#x5EFA;&#x6784;&#x9020;&#x53C2;&#x6570;&#x5217;&#x8868;</span></span><br><span class="line">            argsHolder = createArgumentArray(</span><br><span class="line">                beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);</span><br><span class="line">          }</span><br><span class="line">          <span class="keyword">catch</span> (UnsatisfiedDependencyException ex) {</span><br><span class="line">            <span class="keyword">if</span> (logger.isTraceEnabled()) {</span><br><span class="line">              logger.trace(<span class="string">&quot;Ignoring factory method [&quot;</span> + candidate + <span class="string">&quot;] of bean &apos;&quot;</span> + beanName + <span class="string">&quot;&apos;: &quot;</span> + ex);</span><br><span class="line">            }</span><br><span class="line">            <span class="comment">// Swallow and try next overloaded factory method.</span></span><br><span class="line">            <span class="keyword">if</span> (causes == <span class="keyword">null</span>) {</span><br><span class="line">              causes = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">            }</span><br><span class="line">            causes.add(ex);</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">          }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &#x6839;&#x636E;&#x5B9A;&#x4E49;&#x7684;&#x662F;&#x5426;&#x4E3A;&#x5BBD;&#x677E;&#x6A21;&#x5F0F;&#x6765;&#x505A;&#x7C7B;&#x578B;&#x5DEE;&#x5F02;&#x6743;&#x91CD;&#x7684;&#x5224;&#x65AD;</span></span><br><span class="line">        <span class="keyword">int</span> typeDiffWeight = (mbd.isLenientConstructorResolution() ?</span><br><span class="line">            argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));</span><br><span class="line">        <span class="comment">// &#x9009;&#x62E9;&#x6700;&#x63A5;&#x8FD1;&#x7684;&#x4E00;&#x4E2A;&#x6784;&#x9020;&#x65B9;&#x6CD5;</span></span><br><span class="line">        <span class="keyword">if</span> (typeDiffWeight &lt; minTypeDiffWeight) {</span><br><span class="line">          factoryMethodToUse = candidate;</span><br><span class="line">          argsHolderToUse = argsHolder;</span><br><span class="line">          argsToUse = argsHolder.arguments;</span><br><span class="line">          minTypeDiffWeight = typeDiffWeight;</span><br><span class="line">          ambiguousFactoryMethods = <span class="keyword">null</span>;</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// &#x67E5;&#x51FA;&#x6DF7;&#x6DC6;&#x7684;&#x65B9;&#x6CD5;&#xFF1A;&#x9632;&#x6B62;&#x51FA;&#x73B0;&#x76F8;&#x540C;&#x540D;&#x5B57;&#x3001;&#x76F8;&#x540C;&#x53C2;&#x6570;&#x4E2A;&#x6570;&#x4EE5;&#x53CA;&#x53C2;&#x6570;&#x7C7B;&#x578B;&#x7684;&#x65B9;&#x6CD5;&#xFF1B;</span></span><br><span class="line">        <span class="comment">// &#x6536;&#x96C6;&#x8FD9;&#x4E9B;&#x65B9;&#x6CD5;&#x5E76;&#x5728;&#x51FA;&#x73B0;&#x591A;&#x4E2A;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#x629B;&#x51FA;&#x6DF7;&#x6DC6;&#x5F02;&#x5E38;&#x3002;</span></span><br><span class="line">        <span class="comment">// &#x8FD9;&#x4E2A;&#x68C0;&#x67E5;&#x53EA;&#x4F1A;&#x5728;&#x4E25;&#x683C;&#x6A21;&#x5F0F;&#x4E0B;&#x6267;&#x884C;&#x5E76;&#x4E14;&#x4F1A;&#x5FFD;&#x7565;&#x6389;&#x91CD;&#x5199;&#x7684;&#x65B9;&#x6CD5;&#xFF08;Override&#xFF09;</span></span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (factoryMethodToUse != <span class="keyword">null</span> &amp;&amp; typeDiffWeight == minTypeDiffWeight &amp;&amp;</span><br><span class="line">            !mbd.isLenientConstructorResolution() &amp;&amp;</span><br><span class="line">            paramTypes.length == factoryMethodToUse.getParameterCount() &amp;&amp;</span><br><span class="line">            !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {</span><br><span class="line">          <span class="keyword">if</span> (ambiguousFactoryMethods == <span class="keyword">null</span>) {</span><br><span class="line">            ambiguousFactoryMethods = <span class="keyword">new</span> LinkedHashSet&lt;&gt;();</span><br><span class="line">            ambiguousFactoryMethods.add(factoryMethodToUse);</span><br><span class="line">          }</span><br><span class="line">          ambiguousFactoryMethods.add(candidate);</span><br><span class="line">        }</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x672A;&#x5339;&#x914D;&#x5230;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x7684;&#x5904;&#x7406;&#x903B;&#x8F91;</span></span><br><span class="line">    <span class="keyword">if</span> (factoryMethodToUse == <span class="keyword">null</span>) {</span><br><span class="line">      <span class="comment">// &#x5224;&#x65AD;&#x662F;&#x5426;&#x5B58;&#x5728;&#x5F02;&#x5E38;&#xFF0C;&#x5B58;&#x5728;&#x7684;&#x8BDD;&#xFF0C;&#x6267;&#x884C;Bean&#x7684;&#x56DE;&#x8C03;onSuppressedException&#x65B9;&#x6CD5;&#x540E;&#xFF0C;&#x629B;&#x51FA;&#x5F02;&#x5E38;</span></span><br><span class="line">      <span class="keyword">if</span> (causes != <span class="keyword">null</span>) {</span><br><span class="line">        UnsatisfiedDependencyException ex = causes.removeLast();</span><br><span class="line">        <span class="keyword">for</span> (Exception cause : causes) {</span><br><span class="line">          <span class="keyword">this</span>.beanFactory.onSuppressedException(cause);</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">throw</span> ex;</span><br><span class="line">      }</span><br><span class="line">      <span class="comment">// &#x83B7;&#x53D6;&#x53C2;&#x6570;&#x7C7B;&#x578B;</span></span><br><span class="line">      List&lt;String&gt; argTypes = <span class="keyword">new</span> ArrayList&lt;&gt;(minNrOfArgs);</span><br><span class="line">      <span class="keyword">if</span> (explicitArgs != <span class="keyword">null</span>) {</span><br><span class="line">        <span class="keyword">for</span> (Object arg : explicitArgs) {</span><br><span class="line">          argTypes.add(arg != <span class="keyword">null</span> ? arg.getClass().getSimpleName() : <span class="string">&quot;null&quot;</span>);</span><br><span class="line">        }</span><br><span class="line">      }</span><br><span class="line">      <span class="keyword">else</span> <span class="keyword">if</span> (resolvedValues != <span class="keyword">null</span>){</span><br><span class="line">        Set&lt;ValueHolder&gt; valueHolders = <span class="keyword">new</span> LinkedHashSet&lt;&gt;(resolvedValues.getArgumentCount());</span><br><span class="line">        valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());</span><br><span class="line">        valueHolders.addAll(resolvedValues.getGenericArgumentValues());</span><br><span class="line">        <span class="keyword">for</span> (ValueHolder value : valueHolders) {</span><br><span class="line">          String argType = (value.getType() != <span class="keyword">null</span> ? ClassUtils.getShortName(value.getType()) :</span><br><span class="line">              (value.getValue() != <span class="keyword">null</span> ? value.getValue().getClass().getSimpleName() : <span class="string">&quot;null&quot;</span>));</span><br><span class="line">          argTypes.add(argType);</span><br><span class="line">        }</span><br><span class="line">      }</span><br><span class="line">      String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);</span><br><span class="line">      <span class="comment">// &#x629B;&#x51FA;&#x672A;&#x5339;&#x914D;&#x5230;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x7684;&#x5F02;&#x5E38;</span></span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> BeanCreationException(mbd.getResourceDescription(), beanName,</span><br><span class="line">          <span class="string">&quot;No matching factory method found: &quot;</span> +</span><br><span class="line">          (mbd.getFactoryBeanName() != <span class="keyword">null</span> ?</span><br><span class="line">            <span class="string">&quot;factory bean &apos;&quot;</span> + mbd.getFactoryBeanName() + <span class="string">&quot;&apos;; &quot;</span> : <span class="string">&quot;&quot;</span>) +</span><br><span class="line">          <span class="string">&quot;factory method &apos;&quot;</span> + mbd.getFactoryMethodName() + <span class="string">&quot;(&quot;</span> + argDesc + <span class="string">&quot;)&apos;. &quot;</span> +</span><br><span class="line">          <span class="string">&quot;Check that a method with the specified name &quot;</span> +</span><br><span class="line">          (minNrOfArgs &gt; <span class="number">0</span> ? <span class="string">&quot;and arguments &quot;</span> : <span class="string">&quot;&quot;</span>) +</span><br><span class="line">          <span class="string">&quot;exists and that it is &quot;</span> +</span><br><span class="line">          (isStatic ? <span class="string">&quot;static&quot;</span> : <span class="string">&quot;non-static&quot;</span>) + <span class="string">&quot;.&quot;</span>);</span><br><span class="line">    }</span><br><span class="line">    <span class="comment">// &#x5BF9;&#x4E8E;&#x8FD4;&#x56DE;&#x7C7B;&#x578B;&#x4E3A;void&#x7684;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#xFF0C;&#x629B;&#x51FA;&#x5F02;&#x5E38;</span></span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">void</span>.class == factoryMethodToUse.getReturnType()) {</span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> BeanCreationException(mbd.getResourceDescription(), beanName,</span><br><span class="line">          <span class="string">&quot;Invalid factory method &apos;&quot;</span> + mbd.getFactoryMethodName() +</span><br><span class="line">          <span class="string">&quot;&apos;: needs to have a non-void return type!&quot;</span>);</span><br><span class="line">    }</span><br><span class="line">    <span class="comment">// &#x5B58;&#x5728;&#x591A;&#x4E2A;&#x6DF7;&#x6DC6;&#x65B9;&#x6CD5;&#xFF0C;&#x5219;&#x629B;&#x51FA;&#x5F02;&#x5E38;</span></span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (ambiguousFactoryMethods != <span class="keyword">null</span>) {</span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> BeanCreationException(mbd.getResourceDescription(), beanName,</span><br><span class="line">          <span class="string">&quot;Ambiguous factory method matches found in bean &apos;&quot;</span> + beanName + <span class="string">&quot;&apos; &quot;</span> +</span><br><span class="line">          <span class="string">&quot;(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): &quot;</span> +</span><br><span class="line">          ambiguousFactoryMethods);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x5C06;&#x76F8;&#x5173;&#x7684;&#x6784;&#x5EFA;&#x4FE1;&#x606F;&#x5B58;&#x5165;&#x7F13;&#x5B58;&#xFF0C;&#x7528;&#x4E8E;&#x4EE5;&#x540E;&#x7684;&#x91CD;&#x65B0;&#x521B;&#x5EFA;</span></span><br><span class="line">    <span class="keyword">if</span> (explicitArgs == <span class="keyword">null</span> &amp;&amp; argsHolderToUse != <span class="keyword">null</span>) {</span><br><span class="line">      argsHolderToUse.storeCache(mbd, factoryMethodToUse);</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">try</span> {</span><br><span class="line">    Object beanInstance;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x521B;&#x5EFA;&#x7C7B;&#x5B9E;&#x4F8B;</span></span><br><span class="line">    <span class="keyword">if</span> (System.getSecurityManager() != <span class="keyword">null</span>) {</span><br><span class="line">      <span class="keyword">final</span> Object fb = factoryBean;</span><br><span class="line">      <span class="keyword">final</span> Method factoryMethod = factoryMethodToUse;</span><br><span class="line">      <span class="keyword">final</span> Object[] args = argsToUse;</span><br><span class="line">      beanInstance = AccessController.doPrivileged((PrivilegedAction&lt;Object&gt;) () -&gt;</span><br><span class="line">          beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, beanFactory, fb, factoryMethod, args),</span><br><span class="line">          beanFactory.getAccessControlContext());</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">else</span> {</span><br><span class="line">      beanInstance = <span class="keyword">this</span>.beanFactory.getInstantiationStrategy().instantiate(</span><br><span class="line">          mbd, beanName, <span class="keyword">this</span>.beanFactory, factoryBean, factoryMethodToUse, argsToUse);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    bw.setBeanInstance(beanInstance);</span><br><span class="line">    <span class="keyword">return</span> bw;</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">catch</span> (Throwable ex) {</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> BeanCreationException(mbd.getResourceDescription(), beanName,</span><br><span class="line">        <span class="string">&quot;Bean instantiation via factory method failed&quot;</span>, ex);</span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x5B9E;&#x4F8B;&#x521B;&#x5EFA;&#x8BE6;&#x60C5;&#x5982;&#x4E0B;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> Object <span class="title">instantiate</span><span class="params">(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,</span></span></span><br><span class="line"><span class="function"><span class="params">    @Nullable Object factoryBean, <span class="keyword">final</span> Method factoryMethod, @Nullable Object... args)</span> </span>{</span><br><span class="line"></span><br><span class="line">  <span class="keyword">try</span> {</span><br><span class="line">    <span class="comment">// &#x8BBE;&#x7F6E;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x53EF;&#x8BBF;&#x95EE;</span></span><br><span class="line">    <span class="keyword">if</span> (System.getSecurityManager() != <span class="keyword">null</span>) {</span><br><span class="line">      AccessController.doPrivileged((PrivilegedAction&lt;Object&gt;) () -&gt; {</span><br><span class="line">        ReflectionUtils.makeAccessible(factoryMethod);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">      });</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">else</span> {</span><br><span class="line">      ReflectionUtils.makeAccessible(factoryMethod);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// currentlyInvokedFactoryMethod&#x7528;&#x4E8E;&#x5224;&#x65AD;&#x5F53;&#x524D;&#x7EBF;&#x7A0B;&#x662F;&#x5426;&#x6B63;&#x5728;&#x521B;&#x5EFA;&#x67D0;&#x4E2A;bean</span></span><br><span class="line">    <span class="comment">// &#x88AB;&#x7528;&#x4E8E;BeanMethodInterceptor&#x7C7B;&#x7684;intercept&#x65B9;&#x6CD5;</span></span><br><span class="line">    <span class="comment">// &#x4EE5;&#x53CA;BeanMethodInterceptor&#x7C7B;&#x7684;resolveBeanReference&#x65B9;&#x6CD5;</span></span><br><span class="line">    <span class="comment">// &#x5177;&#x4F53;&#x5E94;&#x7528;&#x573A;&#x666F;&#x4EE5;&#x53CA;&#x76F8;&#x5173;&#x7684;&#x4F7F;&#x7528;&#x60C5;&#x51B5;&#x5F85;&#x63A2;&#x7A76;</span></span><br><span class="line">    <span class="comment">// &#x5907;&#x4EFD;&#x4E4B;&#x524D;&#x7684;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;</span></span><br><span class="line">    Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();</span><br><span class="line">    <span class="keyword">try</span> {</span><br><span class="line">      <span class="comment">// &#x8BBE;&#x7F6E;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x4E3A;&#x5F53;&#x524D;&#x7684;&#x7C7B;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;</span></span><br><span class="line">      currentlyInvokedFactoryMethod.set(factoryMethod);</span><br><span class="line">      <span class="comment">// &#x6267;&#x884C;&#x6784;&#x5EFA;&#x65B9;&#x6CD5;&#x5E76;&#x83B7;&#x5F97;&#x8FD4;&#x56DE;&#x503C;&#xFF0C;&#x5982;&#x679C;&#x8FD4;&#x56DE;&#x503C;&#x4E3A;null&#xFF0C;&#x5219;&#x8FD4;&#x56DE;NullBean&#x5B9E;&#x4F8B;</span></span><br><span class="line">      Object result = factoryMethod.invoke(factoryBean, args);</span><br><span class="line">      <span class="keyword">if</span> (result == <span class="keyword">null</span>) {</span><br><span class="line">        result = <span class="keyword">new</span> NullBean();</span><br><span class="line">      }</span><br><span class="line">      <span class="keyword">return</span> result;</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">finally</span> {</span><br><span class="line">      <span class="comment">// &#x6062;&#x590D;&#x73B0;&#x573A;</span></span><br><span class="line">      <span class="keyword">if</span> (priorInvokedFactoryMethod != <span class="keyword">null</span>) {</span><br><span class="line">        currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);</span><br><span class="line">      }</span><br><span class="line">      <span class="keyword">else</span> {</span><br><span class="line">        currentlyInvokedFactoryMethod.remove();</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">catch</span> (IllegalArgumentException ex) {</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> BeanInstantiationException(factoryMethod,</span><br><span class="line">        <span class="string">&quot;Illegal arguments to factory method &apos;&quot;</span> + factoryMethod.getName() + <span class="string">&quot;&apos;; &quot;</span> +</span><br><span class="line">        <span class="string">&quot;args: &quot;</span> + StringUtils.arrayToCommaDelimitedString(args), ex);</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">catch</span> (IllegalAccessException ex) {</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> BeanInstantiationException(factoryMethod,</span><br><span class="line">        <span class="string">&quot;Cannot access factory method &apos;&quot;</span> + factoryMethod.getName() + <span class="string">&quot;&apos;; is it public?&quot;</span>, ex);</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">catch</span> (InvocationTargetException ex) {</span><br><span class="line">    String msg = <span class="string">&quot;Factory method &apos;&quot;</span> + factoryMethod.getName() + <span class="string">&quot;&apos; threw exception&quot;</span>;</span><br><span class="line">    <span class="keyword">if</span> (bd.getFactoryBeanName() != <span class="keyword">null</span> &amp;&amp; owner <span class="keyword">instanceof</span> ConfigurableBeanFactory &amp;&amp;</span><br><span class="line">        ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {</span><br><span class="line">      msg = <span class="string">&quot;Circular reference involving containing bean &apos;&quot;</span> + bd.getFactoryBeanName() + <span class="string">&quot;&apos; - consider &quot;</span> +</span><br><span class="line">          <span class="string">&quot;declaring the factory method as static for independence from its containing instance. &quot;</span> + msg;</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> BeanInstantiationException(factoryMethod, msg, ex.getTargetException());</span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><h3 id="Bean&#x7684;&#x987A;&#x5E8F;"><a href="#Bean&#x7684;&#x987A;&#x5E8F;" class="headerlink" title="@Bean&#x7684;&#x987A;&#x5E8F;"></a>@Bean&#x7684;&#x987A;&#x5E8F;</h3><p><code>@Bean</code>&#x5982;&#x679C;&#x5728;&#x914D;&#x7F6E;&#x7C7B;&#x5185;&#x90E8;&#xFF0C;&#x5219;&#x53EF;&#x4EE5;&#x6839;&#x636E;&#x5982;&#x4E0B;&#x8FD9;&#x6BB5;&#x4EE3;&#x7801;&#x77E5;&#x9053;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (beanMethods.size() &gt; <span class="number">1</span> &amp;&amp; original <span class="keyword">instanceof</span> StandardAnnotationMetadata) {</span><br><span class="line">  <span class="comment">// &#x5C1D;&#x8BD5;&#x901A;&#x8FC7;ASM&#x4ECE;&#x7C7B;&#x6587;&#x4EF6;&#x5224;&#x65AD;&#x65B9;&#x6CD5;&#x7684;&#x987A;&#x5E8F;...&#x56E0;&#x4E3A;&#xFF0C;JVM&#x7684;&#x6807;&#x51C6;&#x53CD;&#x5C04;&#x5E93;&#x83B7;&#x53D6;&#x7684;&#x65B9;&#x6CD5;&#x987A;&#x5E8F;&#x662F;&#x968F;&#x673A;&#x7684;&#xFF0C;&#x751A;&#x81F3;&#x6CE1;&#x5728;&#x76F8;&#x540C;JVM&#x7684;&#x4E0D;&#x540C;&#x5E94;&#x7528;&#x8FD4;&#x56DE;&#x7684;&#x987A;&#x5E8F;&#x4E5F;&#x4F1A;&#x4E0D;&#x4E00;&#x81F4;</span></span><br><span class="line">  <span class="keyword">try</span> {</span><br><span class="line">    AnnotationMetadata asm =</span><br><span class="line">        <span class="keyword">this</span>.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();</span><br><span class="line">    Set&lt;MethodMetadata&gt; asmMethods = asm.getAnnotatedMethods(Bean.class.getName());</span><br><span class="line">    <span class="keyword">if</span> (asmMethods.size() &gt;= beanMethods.size()) {</span><br><span class="line">      Set&lt;MethodMetadata&gt; selectedMethods = <span class="keyword">new</span> LinkedHashSet&lt;&gt;(asmMethods.size());</span><br><span class="line">      <span class="comment">// &#x505A;&#x4E86;&#x4E00;&#x904D;&#x8FC7;&#x6EE4;&#xFF0C;&#x5C06;&#x4E8C;&#x8FDB;&#x5236;class&#x6587;&#x4EF6;&#x7684;&#x65B9;&#x6CD5;&#x4E0E;JVM&#x53CD;&#x5C04;&#x7684;&#x65B9;&#x6CD5;&#x505A;&#x4E00;&#x6B21;&#x5BF9;&#x6BD4;&#xFF0C;&#x9632;&#x6B62;&#x5C06;&#x975E;&#x7F16;&#x7A0B;&#x65B9;&#x6CD5;&#x52A0;&#x5165;&#xFF0C;&#x4FDD;&#x6301;&#x4E0E;JVM&#x53CD;&#x5C04;&#x83B7;&#x53D6;&#x65B9;&#x6CD5;&#x4E00;&#x81F4;&#xFF0C;&#x9664;&#x4E86;&#x987A;&#x5E8F;&#x3002;</span></span><br><span class="line">      <span class="keyword">for</span> (MethodMetadata asmMethod : asmMethods) {</span><br><span class="line">        <span class="keyword">for</span> (MethodMetadata beanMethod : beanMethods) {</span><br><span class="line">          <span class="keyword">if</span> (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {</span><br><span class="line">            selectedMethods.add(beanMethod);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">          }</span><br><span class="line">        }</span><br><span class="line">      }</span><br><span class="line">      <span class="keyword">if</span> (selectedMethods.size() == beanMethods.size()) {</span><br><span class="line">        <span class="comment">// All reflection-detected methods found in ASM method set -&gt; proceed</span></span><br><span class="line">        beanMethods = selectedMethods;</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">catch</span> (IOException ex) {</span><br><span class="line">    logger.debug(<span class="string">&quot;Failed to read class file via ASM for determining @Bean method order&quot;</span>, ex);</span><br><span class="line">    <span class="comment">// No worries, let&apos;s continue with the reflection metadata we started with...</span></span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x662F;&#x6839;&#x636E;&#x4EE3;&#x7801;&#x7F16;&#x5199;&#x987A;&#x5E8F;&#x6765;&#x6267;&#x884C;&#x3002;</p><p>&#x5982;&#x679C;&#x5B9E;&#x5728;&#x4E0D;&#x540C;&#x7684;<code>Configuration</code>&#x7C7B;&#x5185;&#xFF0C;&#x5219;&#x5224;&#x65AD;&#x4F9D;&#x636E;&#x79FB;&#x690D;&#x5230;&#x7C7B;&#x5C42;&#x6B21;&#x3002;&#x5982;&#x679C;&#x7C7B;&#x5B9E;&#x73B0;&#x4E86;<code>Ordered</code>&#x63A5;&#x53E3;&#x6216;&#x8005;&#x6CE8;&#x89E3;&#x6709;<code>@Order</code>&#x6216;&#x8005;<code>@Prority</code>&#xFF0C;&#x5219;&#x6839;&#x636E;&#x4ED6;&#x4EEC;&#x7684;&#x503C;&#x83B7;&#x53D6;&#x6392;&#x5E8F;&#xFF0C;&#x5426;&#x5219;&#x6839;&#x636E;&#x626B;&#x63CF;&#x7684;&#x987A;&#x5E8F;&#x6765;&#x5224;&#x5B9A;&#x3002;</p><h3 id="Bean&#x7684;&#x8986;&#x76D6;&#x95EE;&#x9898;"><a href="#Bean&#x7684;&#x8986;&#x76D6;&#x95EE;&#x9898;" class="headerlink" title="@Bean&#x7684;&#x8986;&#x76D6;&#x95EE;&#x9898;"></a>@Bean&#x7684;&#x8986;&#x76D6;&#x95EE;&#x9898;</h3><p>&#x5982;&#x679C;&#x5B58;&#x5728;<code>@Bean</code>&#x6CE8;&#x89E3;&#x5185;&#x7684;name&#x76F8;&#x540C;&#x6216;&#x8005;&#x65E0;name&#x65B9;&#x6CD5;&#x540D;&#x76F8;&#x540C;&#xFF0C;&#x5219;&#x6839;&#x636E;<code>@Bean</code>&#x7684;&#x987A;&#x5E8F;&#x6765;&#x8FDB;&#x884C;&#x5BF9;&#x5E94;&#x7684;&#x8986;&#x76D6;&#x3002;</p><h3 id="Spring&#x4F1A;&#x62E6;&#x622A;&#x6240;&#x6709;&#x6807;&#x8BB0;&#x4E3A;-Bean&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x5BB9;&#x5668;&#x5185;&#x5355;&#x4F8B;&#x5BF9;&#x8C61;"><a href="#Spring&#x4F1A;&#x62E6;&#x622A;&#x6240;&#x6709;&#x6807;&#x8BB0;&#x4E3A;-Bean&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x5BB9;&#x5668;&#x5185;&#x5355;&#x4F8B;&#x5BF9;&#x8C61;" class="headerlink" title="Spring&#x4F1A;&#x62E6;&#x622A;&#x6240;&#x6709;&#x6807;&#x8BB0;&#x4E3A;@Bean&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x5BB9;&#x5668;&#x5185;&#x5355;&#x4F8B;&#x5BF9;&#x8C61;"></a>Spring&#x4F1A;&#x62E6;&#x622A;&#x6240;&#x6709;&#x6807;&#x8BB0;&#x4E3A;@Bean&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x5BB9;&#x5668;&#x5185;&#x5355;&#x4F8B;&#x5BF9;&#x8C61;</h3><p>&#x5148;&#x8BF4;&#x7ED3;&#x8BBA;&#xFF0C;&#x8FD9;&#x4E2A;&#x89C2;&#x70B9;&#x662F;&#x9519;&#x8BEF;&#x7684;&#x3002;&#x53EF;&#x4EE5;&#x4ECE;<a href="#@Bean&#x7684;&#x5904;&#x7406;">@Bean&#x7684;&#x5904;&#x7406;</a>&#x4E86;&#x89E3;&#x5230;&#xFF0C;&#x7C7B;&#x7684;&#x521D;&#x59CB;&#x5316;&#xFF0C;&#x5E76;&#x6CA1;&#x6709;&#x5224;&#x65AD;&#x662F;&#x5426;&#x8C03;&#x7528;&#x4E86;&#x5176;&#x4ED6;<code>@Bean</code>&#x6CE8;&#x89E3;&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x662F;&#x901A;&#x8FC7;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Object result = factoryMethod.invoke(factoryBean, args);</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x76F4;&#x63A5;&#x521B;&#x5EFA;&#xFF0C;&#x90A3;&#x4E48;&#x53EF;&#x4EE5;&#x80AF;&#x5B9A;&#x7684;&#x662F;&#xFF1A;&#x8C03;&#x7528;&#x5176;&#x4ED6;<code>@Bean</code>&#x6CE8;&#x89E3;&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x5185;&#x90E8;&#x4F7F;&#x7528;&#x7684;&#x5BF9;&#x8C61;&#x4E0E;<code>@Bean</code>&#x672C;&#x8EAB;&#x521B;&#x5EFA;&#x7684;&#x5BF9;&#x8C61;&#x5E76;&#x4E0D;&#x662F;&#x540C;&#x4E00;&#x4E2A;&#x5BF9;&#x8C61;&#x3002;&#x540C;&#x65F6;&#xFF0C;&#x5982;&#x679C;&#x591A;&#x4E2A;&#x65B9;&#x6CD5;&#x8C03;&#x7528;&#x67D0;&#x4E2A;&#x88AB;&#x6CE8;&#x89E3;&#x6709;<code>@Bean</code>&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x5219;&#x83B7;&#x53D6;&#x7684;&#x5185;&#x90E8;&#x5BF9;&#x8C61;&#x4E5F;&#x662F;&#x4E0D;&#x4E00;&#x6837;&#x7684;&#x3002;</p><h3 id="&#x65B9;&#x6CD5;&#x7EA7;&#x522B;&#x7684;-Bean&#x662F;&#x5426;&#x7531;AOP&#x5B9E;&#x73B0;"><a href="#&#x65B9;&#x6CD5;&#x7EA7;&#x522B;&#x7684;-Bean&#x662F;&#x5426;&#x7531;AOP&#x5B9E;&#x73B0;" class="headerlink" title="&#x65B9;&#x6CD5;&#x7EA7;&#x522B;&#x7684;@Bean&#x662F;&#x5426;&#x7531;AOP&#x5B9E;&#x73B0;"></a>&#x65B9;&#x6CD5;&#x7EA7;&#x522B;&#x7684;@Bean&#x662F;&#x5426;&#x7531;AOP&#x5B9E;&#x73B0;</h3><p>&#x540C;&#x6837;&#x7684;&#xFF0C;&#x521B;&#x5EFA;&#x8FC7;&#x7A0B;&#x4E00;&#x76EE;&#x4E86;&#x7136;&#xFF0C;&#x4E0D;&#x662F;&#x7531;AOP&#x5B9E;&#x73B0;&#xFF1B;&#x4E0D;&#x8FC7;&#xFF0C;&#x5982;&#x679C;&#x663E;&#x793A;&#x6CE8;&#x89E3;&#x4E86;<code>@Scope</code>&#xFF0C;&#x5E76;&#x4E14;&#x975E;NONE&#xFF0C;&#x5219;&#x4F1A;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x8986;&#x76D6;&#x7C7B;&#x5B9A;&#x4E49;&#x3002;&#x8FD9;&#x4E2A;&#x521B;&#x5EFA;&#x8FC7;&#x7A0B;&#x7684;&#x786E;&#x4F7F;&#x7528;&#x4E86;&#x7C7B;AOP&#x7684;&#x6982;&#x5FF5;&#x3002;</p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;前提&quot;&gt;&lt;a href=&quot;#前提&quot; class=&quot;headerlink&quot; title=&quot;前提&quot;&gt;&lt;/a&gt;前提&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Spring 5&lt;/li&gt;&lt;li&gt;基于Java Configuration配置，而非XML配置&lt;/li&gt;&lt;li&gt;非Web环境&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;Bean的处理&quot;&gt;&lt;a href=&quot;#Bean的处理&quot; class=&quot;headerlink&quot; title=&quot;@Bean的处理&quot;&gt;&lt;/a&gt;@Bean的处理&lt;/h3&gt;&lt;p&gt;与AOP构造器的创建过程类似（具体的可以查看这篇文章：&lt;a href=&quot;https://xuqiang.me/多个AspectJ对同一个对象操作产生的实际效果以及顺序情况.html&quot;&gt;多个AspectJ对同一个对象操作产生的实际效果以及顺序情况&lt;/a&gt;）,&lt;code&gt;@Bean&lt;/code&gt;的处理也是在&lt;code&gt;ConfigurationClassParser&lt;/code&gt;类的&lt;code&gt;doProcessConfigurationClass&lt;/code&gt;方法内做的处理：&lt;br&gt;&lt;/p&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Process individual @Bean methods&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Set&amp;lt;MethodMetadata&amp;gt; beanMethods = retrieveBeanMethodMetadata(sourceClass);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (MethodMetadata methodMetadata : beanMethods) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  configClass.addBeanMethod(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BeanMethod(methodMetadata, configClass));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;之后在&lt;code&gt;ConfigurationClassPostProcessor&lt;/code&gt;类的&lt;code&gt;processConfigBeanDefinitions&lt;/code&gt;方法内解析：&lt;br&gt;&lt;/p&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Read the model and create bean definitions based on its content&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.reader == &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.reader = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; ConfigurationClassBeanDefinitionReader(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      registry, &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.sourceExtractor, &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.resourceLoader, &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.environment,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.importBeanNameGenerator, parser.getImportRegistry());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.reader.loadBeanDefinitions(configClasses);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="Spring" scheme="https://xuqiang.me/categories/Java/Spring/"/>
    
      <category term="SpringSources" scheme="https://xuqiang.me/categories/Java/Spring/SpringSources/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="bean" scheme="https://xuqiang.me/tags/bean/"/>
    
      <category term="aop" scheme="https://xuqiang.me/tags/aop/"/>
    
      <category term="spring" scheme="https://xuqiang.me/tags/spring/"/>
    
  </entry>
  
  <entry>
    <title>多个AspectJ对同一个对象操作产生的实际效果以及顺序情况</title>
    <link href="https://xuqiang.me/%E5%A4%9A%E4%B8%AAAspectJ%E5%AF%B9%E5%90%8C%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E6%93%8D%E4%BD%9C%E4%BA%A7%E7%94%9F%E7%9A%84%E5%AE%9E%E9%99%85%E6%95%88%E6%9E%9C%E4%BB%A5%E5%8F%8A%E9%A1%BA%E5%BA%8F%E6%83%85%E5%86%B5.html"/>
    <id>https://xuqiang.me/多个AspectJ对同一个对象操作产生的实际效果以及顺序情况.html</id>
    <published>2018-08-20T15:11:39.000Z</published>
    <updated>2018-08-20T15:14:10.539Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x524D;&#x63D0;"><a href="#&#x524D;&#x63D0;" class="headerlink" title="&#x524D;&#x63D0;"></a>&#x524D;&#x63D0;</h3><ul><li>Spring 5</li><li>&#x57FA;&#x4E8E;Java Configuration&#x914D;&#x7F6E;&#xFF0C;&#x800C;&#x975E;XML&#x914D;&#x7F6E;</li><li>&#x5BF9;&#x4E8E;AspectJ&#x7684;&#x5206;&#x6790;&#xFF0C;&#x4E0D;&#x5BF9;Spring&#x672C;&#x8EAB;&#x7684;Advisor&#x505A;&#x5206;&#x6790;</li></ul><h3 id="&#x6982;&#x8981;"><a href="#&#x6982;&#x8981;" class="headerlink" title="&#x6982;&#x8981;"></a>&#x6982;&#x8981;</h3><p>&#x5982;&#x679C;&#x9700;&#x8981;&#x4E86;&#x89E3;&#x591A;&#x4E2A;AscpectJ&#x5BF9;&#x540C;&#x4E00;&#x4E2A;&#x5BF9;&#x8C61;&#x64CD;&#x4F5C;&#x4EA7;&#x751F;&#x7684;&#x5B9E;&#x9645;&#x6548;&#x679C;&#x4EE5;&#x53CA;&#x4F5C;&#x7528;&#x987A;&#x5E8F;&#xFF0C;&#x5219;&#x9700;&#x8981;&#x9996;&#x5148;&#x4E86;&#x89E3;AOP&#x5BF9;&#x8C61;&#x7684;&#x6784;&#x5EFA;&#x8FC7;&#x7A0B;&#xFF0C;&#x4EE5;&#x53CA;&#x5982;&#x4F55;&#x7EC7;&#x5165;&#xFF0C;&#x8FD8;&#x6709;&#x5C31;&#x662F;&#x7EC7;&#x5165;&#x8FC7;&#x7A0B;&#x4E2D;&#x7684;&#x987A;&#x5E8F;&#x903B;&#x8F91;&#x7684;&#x4E86;&#x89E3;&#x3002;</p><p>&#x6240;&#x4EE5;&#xFF0C;&#x8FD9;&#x7BC7;&#x6587;&#x7AE0;&#x4E3B;&#x8981;&#x5185;&#x5BB9;&#x5982;&#x4E0B;&#xFF1A;</p><ul><li><a href="#AOP&#x6784;&#x9020;&#x8005;&#x6CE8;&#x518C;">AOP&#x6784;&#x9020;&#x8005;&#x6CE8;&#x518C;</a></li><li><a href="#AOP&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x7684;&#x521D;&#x59CB;&#x5316;&#x6784;&#x5EFA;">AOP&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x7684;&#x521D;&#x59CB;&#x5316;&#x6784;&#x5EFA;</a></li><li><a href="#AOP%20advice&#x7684;&#x987A;&#x5E8F;&#x95EE;&#x9898;">AOP advice&#x7684;&#x987A;&#x5E8F;&#x95EE;&#x9898;</a></li><li><a href="#AOP%20advice&#x7684;&#x5177;&#x4F53;&#x8C03;&#x7528;">AOP advice&#x7684;&#x5177;&#x4F53;&#x8C03;&#x7528;</a></li></ul><a id="more"></a><h3 id="AOP&#x6784;&#x9020;&#x8005;&#x6CE8;&#x518C;"><a href="#AOP&#x6784;&#x9020;&#x8005;&#x6CE8;&#x518C;" class="headerlink" title="AOP&#x6784;&#x9020;&#x8005;&#x6CE8;&#x518C;"></a>AOP&#x6784;&#x9020;&#x8005;&#x6CE8;&#x518C;</h3><p>AOP&#x6784;&#x9020;&#x8005;&#x7684;&#x6CE8;&#x518C;&#x662F;&#x901A;&#x8FC7;Spring&#x7684;Import&#x673A;&#x5236;&#x5B9E;&#x73B0;&#x3002;&#x5728;<code>EnableAspectJAutoProxy</code>&#x6CE8;&#x89E3;&#x4E0A;&#xFF0C;&#x5B58;&#x5728;@Import&#x6CE8;&#x89E3;&#xFF0C;&#x5176;&#x5185;&#x90E8;&#x6709;&#x5B9E;&#x73B0;&#x4E86;<code>ImportBeanDefinitionRegistrar</code>&#x63A5;&#x53E3;&#x7684;<code>AspectJAutoProxyRegistrar</code>&#x7C7B;&#x3002;</p><p>&#x5728;&#x8FD9;&#x91CC;&#x7B80;&#x5355;&#x4ECB;&#x7ECD;&#x4E0B;<code>ImportBeanDefinitionRegistrar</code>&#x63A5;&#x53E3;&#x3002;</p><p><code>ImportBeanDefinitionRegistrar</code>&#x63A5;&#x53E3;&#x5E38;&#x88AB;&#x7528;&#x4E8E;Spring&#x52A8;&#x6001;bean&#x6CE8;&#x518C;&#x3002;&#x8FD9;&#x4E2A;&#x63A5;&#x53E3;&#x4F1A;&#x88AB;<code>ConfigurationClassPostProcessor</code>&#x7C7B;&#x5185;&#x7684;<code>ConfigurationClassParser</code>&#x4EE3;&#x7406;&#x7C7B;&#x89E3;&#x6790;&#xFF0C;&#x5E76;&#x901A;&#x8FC7;<code>ConfigurationClassBeanDefinitionReader</code>&#x7C7B;&#x7684;<code>loadBeanDefinitions</code>&#x65B9;&#x6CD5;&#x8C03;&#x7528;&#x6240;&#x6709;&#x5B9E;&#x73B0;&#x4E86;<code>ImportBeanDefinitionRegistrar</code>&#x63A5;&#x53E3;&#x7C7B;&#x7684;<code>registerBeanDefinitions</code>&#x65B9;&#x6CD5;&#x3002;</p><p>&#x4EE5;&#x4E0B;&#x662F;<code>ImportBeanDefinitionRegistrar</code>&#x7C7B;&#x6267;&#x884C;<code>registerBeanDefinitions</code>&#x7684;&#x8FC7;&#x7A0B;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1. &#x5BB9;&#x5668;&#x4E0A;&#x4E0B;&#x6587;&#x6CE8;&#x518C;</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">AnnotationConfigApplicationContext</span><span class="params">(Class&lt;?&gt;... annotatedClasses)</span> </span>{</span><br><span class="line">  <span class="keyword">this</span>();</span><br><span class="line">  register(annotatedClasses);</span><br><span class="line">  <span class="comment">// &#x5237;&#x65B0;</span></span><br><span class="line">  refresh();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2. &#x6267;&#x884C;invokeBeanFactoryPostProcessors</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">refresh</span><span class="params">()</span> <span class="keyword">throws</span> BeansException, IllegalStateException </span>{</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">  invokeBeanFactoryPostProcessors(beanFactory);</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 3. &#x6267;&#x884C;PostProcessor&#x4EE3;&#x7406;&#x7C7B;&#x7684;invokeBeanFactoryPostProcessors&#x65B9;&#x6CD5;</span></span><br><span class="line">PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());</span><br><span class="line"></span><br><span class="line"><span class="comment">// 4. &#x5FAA;&#x73AF;&#x6240;&#x6709;&#x7684;beanProcessors</span></span><br><span class="line"><span class="keyword">for</span> (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {</span><br><span class="line">  postProcessor.postProcessBeanDefinitionRegistry(registry);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 5. &#x6267;&#x884C;ConfigurationClassPostProcessor&#x7C7B;&#x7684;postProcessBeanDefinitionRegistry&#x65B9;&#x6CD5;</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">postProcessBeanDefinitionRegistry</span><span class="params">(BeanDefinitionRegistry registry)</span> </span>{</span><br><span class="line">  processConfigBeanDefinitions(registry);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 6. &#x5B9E;&#x4F8B;&#x5316;ConfigurationClassParser&#x7C7B;&#xFF0C;&#x5E76;&#x6267;&#x884C;&#x89E3;&#x6790;&#x64CD;&#x4F5C;&#xFF08;&#x6BD4;&#x5982;@PropertySources&#x3001;@ComponentScans&#x3001;@Import&#x3001;@ImportSelectors&#x7B49;&#x7B49;&#x6CE8;&#x89E3;&#x7684;&#x89E3;&#x6790;&#x5904;&#x7406;&#xFF09;</span></span><br><span class="line">ConfigurationClassParser parser = <span class="keyword">new</span> ConfigurationClassParser(</span><br><span class="line"><span class="keyword">this</span>.metadataReaderFactory, <span class="keyword">this</span>.problemReporter, <span class="keyword">this</span>.environment,</span><br><span class="line"><span class="keyword">this</span>.resourceLoader, <span class="keyword">this</span>.componentScanBeanNameGenerator, registry);</span><br><span class="line"></span><br><span class="line">Set&lt;BeanDefinitionHolder&gt; candidates = <span class="keyword">new</span> LinkedHashSet&lt;&gt;(configCandidates);</span><br><span class="line">parser.parse(candidates);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 7. &#x52A0;&#x8F7D;Bean&#x89E3;&#x6790;&#x4FE1;&#x606F;</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">this</span>.reader == <span class="keyword">null</span>) {</span><br><span class="line">  <span class="keyword">this</span>.reader = <span class="keyword">new</span> ConfigurationClassBeanDefinitionReader(</span><br><span class="line">      registry, <span class="keyword">this</span>.sourceExtractor, <span class="keyword">this</span>.resourceLoader, <span class="keyword">this</span>.environment,</span><br><span class="line">      <span class="keyword">this</span>.importBeanNameGenerator, parser.getImportRegistry());</span><br><span class="line">}</span><br><span class="line"><span class="keyword">this</span>.reader.loadBeanDefinitions(configClasses);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 8. &#x4ECE;&#x914D;&#x7F6E;&#x7C7B;&#x52A0;&#x8F7D;Bean&#x89E3;&#x6790;&#x4FE1;&#x606F;</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">loadBeanDefinitionsForConfigurationClass</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator)</span> </span>{</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (trackedConditionEvaluator.shouldSkip(configClass)) {</span><br><span class="line">    String beanName = configClass.getBeanName();</span><br><span class="line">    <span class="keyword">if</span> (StringUtils.hasLength(beanName) &amp;&amp; <span class="keyword">this</span>.registry.containsBeanDefinition(beanName)) {</span><br><span class="line">      <span class="keyword">this</span>.registry.removeBeanDefinition(beanName);</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">this</span>.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (configClass.isImported()) {</span><br><span class="line">    registerBeanDefinitionForImportedConfigurationClass(configClass);</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">for</span> (BeanMethod beanMethod : configClass.getBeanMethods()) {</span><br><span class="line">    loadBeanDefinitionsForBeanMethod(beanMethod);</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());</span><br><span class="line">  <span class="comment">// &#x52A0;&#x8F7D;Import registry&#x7684;&#x4FE1;&#x606F;</span></span><br><span class="line">  loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="number">9</span>. ImportBeanDefinitionRegistrar&#x6267;&#x884C;bean&#x89E3;&#x6790;</span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">loadBeanDefinitionsFromRegistrars</span><span class="params">(Map&lt;ImportBeanDefinitionRegistrar, AnnotationMetadata&gt; registrars)</span> </span>{</span><br><span class="line">  registrars.forEach((registrar, metadata) -&gt;</span><br><span class="line">      registrar.registerBeanDefinitions(metadata, <span class="keyword">this</span>.registry));</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x5728;&#x6CE8;&#x518C;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;<code>ImportBeanDefinitionRegistrar</code>&#x7C7B;&#x5148;&#x5C06;<code>AnnotationAwareAspectJAutoProxyCreator</code>&#x6CE8;&#x518C;&#x5230;&#x4E86;Bean&#x5BB9;&#x5668;&#x5185;&#xFF0C;&#x7136;&#x540E;&#x901A;&#x8FC7;<code>EnableAspectJAutoProxy</code>&#x6CE8;&#x89E3;&#xFF0C;&#x5C06;<code>proxyTargetClass</code>&#x548C;<code>exposeProxy</code>&#x5C5E;&#x6027;&#x6CE8;&#x5165;&#x5230; <code>AnnotationAwareAspectJAutoProxyCreator</code>&#x7C7B;&#x7684;bean&#x5B9A;&#x4E49;&#x5185;&#x3002;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5C06;AnnotationAwareAspectJAutoProxyCreator&#x6CE8;&#x518C;&#x5230;Bean&#x5BB9;&#x5668;</span></span><br><span class="line">AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);</span><br><span class="line"></span><br><span class="line">AnnotationAttributes enableAspectJAutoProxy =</span><br><span class="line">    AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);</span><br><span class="line"><span class="keyword">if</span> (enableAspectJAutoProxy != <span class="keyword">null</span>) {</span><br><span class="line">  <span class="keyword">if</span> (enableAspectJAutoProxy.getBoolean(<span class="string">&quot;proxyTargetClass&quot;</span>)) {</span><br><span class="line">    <span class="comment">// &#x6CE8;&#x518C;&#x5C5E;&#x6027;proxyTargetClass</span></span><br><span class="line">    AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">if</span> (enableAspectJAutoProxy.getBoolean(<span class="string">&quot;exposeProxy&quot;</span>)) {</span><br><span class="line">    <span class="comment">// &#x6CE8;&#x518C;&#x5C5E;&#x6027;exposeProxy</span></span><br><span class="line">    AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);</span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><h3 id="AOP&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x7684;&#x521D;&#x59CB;&#x5316;&#x6784;&#x5EFA;"><a href="#AOP&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x7684;&#x521D;&#x59CB;&#x5316;&#x6784;&#x5EFA;" class="headerlink" title="AOP&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x7684;&#x521D;&#x59CB;&#x5316;&#x6784;&#x5EFA;"></a>AOP&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x7684;&#x521D;&#x59CB;&#x5316;&#x6784;&#x5EFA;</h3><p>AOP&#x7684;&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x662F;&#x5728;<code>BeanPostProcesser</code>&#x7684;&#x5904;&#x7406;&#x56DE;&#x8C03;&#x5185;&#x521B;&#x5EFA;&#x7684;&#xFF0C;AOP&#x7684;&#x4EE3;&#x7406;&#x521B;&#x5EFA;&#x7C7B;&#x5B9E;&#x73B0;&#x4E86;<code>BeanPostProcesser</code>&#x7684;&#x63A5;&#x53E3;&#xFF0C;&#x8BE5;&#x7C7B;&#x540D;&#x4E3A;<code>AnnotationAwareAspectJAutoProxyCreator</code>&#x3002;</p><p>&#x672C;&#x8D28;&#x4E0A;&#x6765;&#x8BF4;&#xFF0C;&#x662F;&#x5B83;&#x7684;&#x7236;&#x7C7B;<code>AbstractAutoProxyCreator</code>&#x5B9E;&#x73B0;&#x4E86;<code>SmartInstantiationAwareBeanPostProcessor</code>&#x63A5;&#x53E3;&#xFF0C;&#x800C;&#x8FD9;&#x4E2A;&#x63A5;&#x53E3;&#x7EE7;&#x627F;&#x4E86;<code>InstantiationAwareBeanPostProcessor</code>&#x63A5;&#x53E3;&#xFF0C;&#x540C;&#x65F6;<code>InstantiationAwareBeanPostProcessor</code>&#x63A5;&#x53E3;&#x7EE7;&#x627F;&#x4E86;<code>BeanPostProcesser</code>&#x63A5;&#x53E3;&#x3002;</p><p>&#x5728;&#x7C7B;&#x521D;&#x59CB;&#x5316;&#x5B8C;&#x6210;&#x540E;&#xFF0C;&#x4F1A;&#x8C03;&#x7528;<code>AbstractAutoProxyCreator</code>&#x7C7B;&#x7684;<code>postProcessAfterInitialization</code>&#x65B9;&#x6CD5;&#xFF0C;&#x5728;&#x8FD9;&#x4E2A;&#x65B9;&#x6CD5;&#x5185;&#xFF0C;&#x4F1A;&#x83B7;&#x53D6;&#x76EE;&#x6807;&#x5BF9;&#x8C61;&#x7684;&#x6240;&#x6709;<code>advice</code>&#x6765;&#x5224;&#x65AD;&#x662F;&#x5426;&#x9700;&#x8981;&#x6784;&#x5EFA;&#x4EE3;&#x7406;&#x7C7B;&#x3002;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, <span class="keyword">null</span>);</span><br><span class="line"><span class="keyword">if</span> (specificInterceptors != DO_NOT_PROXY) {</span><br><span class="line">  <span class="comment">// &#x9700;&#x8981;&#x4EE3;&#x7406;&#xFF0C;&#x521B;&#x5EFA;&#x5177;&#x4F53;&#x7684;&#x4EE3;&#x7406;&#x7C7B;</span></span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x5177;&#x4F53;&#x6765;&#x770B;&#x4E00;&#x4E0B;<code>getAdvicesAndAdvisorsForBean</code>&#x65B9;&#x6CD5;&#xFF0C;&#x4E3B;&#x8981;&#x662F;&#x641C;&#x7D22;<code>Advisor</code>&#x7C7B;&#x7684;&#x5B9E;&#x73B0;&#x548C;&#x6807;&#x6CE8;&#x6709;<code>@Aspect</code>&#x6CE8;&#x89E3;&#x7684;&#x7C7B;&#xFF0C;&#x5E76;&#x4E14;&#x83B7;&#x53D6;<code>@Aspect</code>&#x6CE8;&#x89E3;&#x7C7B;&#x5185;&#x7684;&#x5207;&#x9762;&#x70B9;&#xFF08;&#x4EE5;&#x4E0B;&#x903B;&#x8F91;&#x5185;&#x5BB9;&#x5B9E;&#x73B0;&#x5728;<code>AnnotationAwareAspectJAutoProxyCreator</code>&#x7C7B;&#x5185;&#xFF0C;&#x8986;&#x76D6;&#x4E86;&#x7236;&#x7C7B;<code>AbstractAutoProxyCreator</code>&#x7684;<code>findCandidateAdvisors</code>&#x65B9;&#x6CD5;&#xFF09;&#x3002;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Add all the Spring advisors found according to superclass rules.</span></span><br><span class="line">List&lt;Advisor&gt; advisors = <span class="keyword">super</span>.findCandidateAdvisors();</span><br><span class="line"><span class="comment">// Build Advisors for all AspectJ aspects in the bean factory.</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">this</span>.aspectJAdvisorsBuilder != <span class="keyword">null</span>) {</span><br><span class="line">  advisors.addAll(<span class="keyword">this</span>.aspectJAdvisorsBuilder.buildAspectJAdvisors());</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> advisors;</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x5982;&#x679C;&#x6CA1;&#x6709;&#x5B9E;&#x73B0;<code>Advisor</code>&#x63A5;&#x53E3;&#x7C7B;&#xFF0C;&#x5219;super.findCandidateAdvisors()&#x8FD4;&#x56DE;&#x7684;&#x4F1A;&#x662F;&#x4E00;&#x4E2A;&#x7A7A;&#x5217;&#x8868;&#x3002;&#x672C;&#x6587;&#x4E5F;&#x4E3B;&#x8981;&#x63A2;&#x7A76;&#x7684;&#x662F;AspectJ&#x76F8;&#x5173;&#x7684;&#x5177;&#x4F53;&#x5B9E;&#x73B0;&#x903B;&#x8F91;&#xFF0C;&#x6240;&#x4EE5;&#x5FFD;&#x7565;&#x7236;&#x7C7B;&#x7684;<code>Advisor</code>&#x641C;&#x7D22;&#x903B;&#x8F91;&#xFF0C;&#x6765;&#x5177;&#x4F53;&#x770B;&#x4E00;&#x4E0B;<code>buildAspectJAdvisors</code>&#x65B9;&#x6CD5;&#x3002;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// this.aspectBeanNames&#x7F13;&#x5B58;&#x7684;&#x662F;&#x672C;&#x6B21;&#x5BB9;&#x5668;&#x542F;&#x52A8;&#x540E;&#x7684;&#x5207;&#x9762;&#x7C7B;&#x540D;&#x79F0;&#x5217;&#x8868;&#xFF0C;&#x5982;&#x679C;&#x521A;&#x542F;&#x52A8;&#xFF0C;&#x5219;&#x4E3A;&#x7A7A;</span></span><br><span class="line">List&lt;String&gt; aspectNames = <span class="keyword">this</span>.aspectBeanNames;</span><br><span class="line"></span><br><span class="line"><span class="comment">// &#x5224;&#x65AD;&#x662F;&#x5426;&#x4E3A;null&#xFF0C;&#x5982;&#x679C;&#x662F;&#x7684;&#x8BDD;&#xFF0C;&#x9501;&#x7C7B;&#x5E76;&#x4E14;&#x521D;&#x59CB;&#x5316;&#x5207;&#x9762;&#x7C7B;&#x540D;&#x79F0;</span></span><br><span class="line"><span class="keyword">if</span> (aspectNames == <span class="keyword">null</span>) {</span><br><span class="line">  <span class="keyword">synchronized</span> (<span class="keyword">this</span>) {</span><br><span class="line">    <span class="comment">// &#x518D;&#x6B21;&#x5224;&#x65AD;&#x662F;&#x5426;&#x4E3A;&#x7A7A;&#xFF0C;&#x786E;&#x4FDD;&#x5176;&#x4ED6;&#x7EBF;&#x7A0B;&#x5728;&#x83B7;&#x53D6;&#x9501;&#x540E;&#x4E0D;&#x4F1A;&#x91CD;&#x590D;&#x505A;&#x521D;&#x59CB;&#x5316;&#x64CD;&#x4F5C;</span></span><br><span class="line">    aspectNames = <span class="keyword">this</span>.aspectBeanNames;</span><br><span class="line">    <span class="keyword">if</span> (aspectNames == <span class="keyword">null</span>) {</span><br><span class="line">      List&lt;Advisor&gt; advisors = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">      aspectNames = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">      <span class="comment">// &#x67E5;&#x627E;&#x6240;&#x6709;&#x7236;&#x7C7B;&#x4E3A;Object&#x7684;bean&#x5BF9;&#x8C61;</span></span><br><span class="line">      String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(</span><br><span class="line">          <span class="keyword">this</span>.beanFactory, Object.class, <span class="keyword">true</span>, <span class="keyword">false</span>);</span><br><span class="line">      <span class="keyword">for</span> (String beanName : beanNames) {</span><br><span class="line">        <span class="comment">// &#x5224;&#x65AD;&#x662F;&#x5426;&#x9700;&#x8981;&#x901A;&#x8FC7;[includePatterns]&#x5C5E;&#x6027;&#x8FC7;&#x6EE4;&#xFF0C;&#x4E0D;&#x8FC7;Java&#x914D;&#x7F6E;&#x7684;AOP&#x8C8C;&#x4F3C;&#x4E0D;&#x652F;&#x6301;&#x8FD9;&#x4E2A;&#x5C5E;&#x6027;&#xFF0C;&#x4E5F;&#x53EF;&#x80FD;&#x662F;&#x6CA1;&#x627E;&#x5230;&#x5728;&#x54EA;&#x91CC;</span></span><br><span class="line">        <span class="keyword">if</span> (!isEligibleBean(beanName)) {</span><br><span class="line">          <span class="keyword">continue</span>;</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// &#x5728;&#x8FD9;&#x91CC;&#x4E0D;&#x9700;&#x8981;&#x7ACB;&#x5373;&#x5B9E;&#x4F8B;&#x5316;&#x7C7B;&#xFF1B;&#x56E0;&#x4E3A;&#xFF0C;&#x901A;&#x8FC7;getType&#x65B9;&#x6CD5;&#x5B83;&#x4F1A;&#x88AB;Spring&#x5BB9;&#x5668;&#x7F13;&#x5B58;&#xFF0C;&#x4F46;&#x662F;&#x5374;&#x4E0D;&#x4F1A;&#x88AB;&#x7EC7;&#x5165;</span></span><br><span class="line">        Class&lt;?&gt; beanType = <span class="keyword">this</span>.beanFactory.getType(beanName);</span><br><span class="line">        <span class="keyword">if</span> (beanType == <span class="keyword">null</span>) {</span><br><span class="line">          <span class="keyword">continue</span>;</span><br><span class="line">        }</span><br><span class="line">        <span class="comment">// &#x5224;&#x65AD;&#x83B7;&#x53D6;&#x7684;&#x7C7B;&#x662F;&#x5426;&#x4E3A;Aspect&#x7C7B;</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span>.advisorFactory.isAspect(beanType)) {</span><br><span class="line">          <span class="comment">// &#x5982;&#x679C;&#x662F;&#x7684;&#x8BDD;&#xFF0C;&#x5219;&#x5C06;&#x7C7B;&#x52A0;&#x5165;&#x5207;&#x9762;&#x7C7B;&#x540D;&#x79F0;&#x5217;&#x8868;&#x5185;</span></span><br><span class="line">          aspectNames.add(beanName);</span><br><span class="line">          <span class="comment">// &#x521D;&#x59CB;&#x5316;&#x5207;&#x9762;&#x5143;&#x6570;&#x636E;</span></span><br><span class="line">          AspectMetadata amd = <span class="keyword">new</span> AspectMetadata(beanType, beanName);</span><br><span class="line">          <span class="comment">// &#x5224;&#x65AD;&#x5207;&#x9762;&#x7C7B;&#x662F;&#x5426;&#x4E3A;&#x5355;&#x4F8B;&#x7C7B;&#x578B;</span></span><br><span class="line">          <span class="keyword">if</span> (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {</span><br><span class="line">            MetadataAwareAspectInstanceFactory factory =</span><br><span class="line">                <span class="keyword">new</span> BeanFactoryAspectInstanceFactory(<span class="keyword">this</span>.beanFactory, beanName);</span><br><span class="line">            <span class="comment">// &#x901A;&#x8FC7;bean&#x5DE5;&#x5382;&#x7C7B;&#x83B7;&#x53D6;&#x5BF9;&#x5E94;&#x5207;&#x9762;&#x7C7B;&#x7684;&#x6240;&#x6709;Advisor</span></span><br><span class="line">            List&lt;Advisor&gt; classAdvisors = <span class="keyword">this</span>.advisorFactory.getAdvisors(factory);</span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">this</span>.beanFactory.isSingleton(beanName)) {</span><br><span class="line">              <span class="comment">// &#x5982;&#x679C;bean&#x5DE5;&#x5382;&#x7C7B;&#x4E3A;&#x5355;&#x4F8B;&#xFF0C;&#x5219;&#x5C06;Advisors&#x7F13;&#x5B58;&#x5230;key&#x4E3A;&#x5207;&#x9762;&#x7C7B;&#x540D;&#x7684;advisorsCache&#x5185;</span></span><br><span class="line">              <span class="keyword">this</span>.advisorsCache.put(beanName, classAdvisors);</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span> {</span><br><span class="line">              <span class="comment">// &#x5982;&#x679C;bean&#x5DE5;&#x5382;&#x7C7B;&#x4E0D;&#x4E3A;&#x5B9E;&#x4F8B;&#xFF0C;&#x5219;&#x7F13;&#x5B58;&#x7F13;&#x5B58;&#x5230;key&#x4E3A;&#x5207;&#x9762;&#x7C7B;&#x540D;&#x7684;aspectFactoryCache&#x5185;</span></span><br><span class="line">              <span class="keyword">this</span>.aspectFactoryCache.put(beanName, factory);</span><br><span class="line">            }</span><br><span class="line">            <span class="comment">// &#x5C06;&#x6240;&#x6709;&#x7684;Advisors&#x7F13;&#x5B58;&#x5230;advisors&#x5217;&#x8868;&#x5185;</span></span><br><span class="line">            advisors.addAll(classAdvisors);</span><br><span class="line">          }</span><br><span class="line">          <span class="keyword">else</span> {</span><br><span class="line">            <span class="comment">// &#x6BCF;&#x4E2A;&#x5207;&#x9762;&#x7C7B;&#x9700;&#x8981;&#x5BF9;&#x5E94;&#x6709;&#x5DE5;&#x5382;&#x7C7B;</span></span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">this</span>.beanFactory.isSingleton(beanName)) {</span><br><span class="line">              <span class="comment">// &#x5982;&#x679C;&#x5DE5;&#x5382;&#x7C7B;&#x662F;&#x5355;&#x4F8B;&#xFF0C;&#x5219;&#x629B;&#x51FA;&#x5F02;&#x5E38;</span></span><br><span class="line">              <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">&quot;Bean with name &apos;&quot;</span> + beanName +</span><br><span class="line">                  <span class="string">&quot;&apos; is a singleton, but aspect instantiation model is not singleton&quot;</span>);</span><br><span class="line">            }</span><br><span class="line">            <span class="comment">// &#x7F13;&#x5B58;&#x7F13;&#x5B58;&#x5230;key&#x4E3A;&#x5207;&#x9762;&#x7C7B;&#x540D;&#x7684;aspectFactoryCache&#x5185;</span></span><br><span class="line">            MetadataAwareAspectInstanceFactory factory =</span><br><span class="line">                <span class="keyword">new</span> PrototypeAspectInstanceFactory(<span class="keyword">this</span>.beanFactory, beanName);</span><br><span class="line">            <span class="keyword">this</span>.aspectFactoryCache.put(beanName, factory);</span><br><span class="line">            advisors.addAll(<span class="keyword">this</span>.advisorFactory.getAdvisors(factory));</span><br><span class="line">          }</span><br><span class="line">        }</span><br><span class="line">      }</span><br><span class="line">      <span class="keyword">this</span>.aspectBeanNames = aspectNames;</span><br><span class="line">      <span class="keyword">return</span> advisors;</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// &#x5207;&#x9762;&#x7C7B;&#x540D;&#x79F0;&#x5217;&#x8868;&#x4E0D;&#x4E3A;null</span></span><br><span class="line"><span class="comment">// &#x5224;&#x65AD;&#x83B7;&#x53D6;&#x5230;&#x7684;&#x5207;&#x9762;&#x7C7B;&#x540D;&#x79F0;&#x5217;&#x8868;&#x662F;&#x5426;&#x4E3A;&#x7A7A;</span></span><br><span class="line"><span class="keyword">if</span> (aspectNames.isEmpty()) {</span><br><span class="line">  <span class="keyword">return</span> Collections.emptyList();</span><br><span class="line">}</span><br><span class="line">List&lt;Advisor&gt; advisors = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"><span class="keyword">for</span> (String aspectName : aspectNames) {</span><br><span class="line">  <span class="comment">// &#x4ECE;advisorsCache&#x5185;&#x83B7;&#x53D6;&#x5207;&#x9762;&#x7C7B;&#x7684;&#x6240;&#x6709;Advisors</span></span><br><span class="line">  List&lt;Advisor&gt; cachedAdvisors = <span class="keyword">this</span>.advisorsCache.get(aspectName);</span><br><span class="line">  <span class="keyword">if</span> (cachedAdvisors != <span class="keyword">null</span>) {</span><br><span class="line">    advisors.addAll(cachedAdvisors);</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">else</span> {</span><br><span class="line">    <span class="comment">// &#x5982;&#x679C;cachedAdvisors&#x4E3A;&#x7A7A;&#xFF0C;&#x5219;&#x4ECE;aspectFactoryCache&#x7F13;&#x5B58;&#x5185;&#x83B7;&#x53D6;bean&#x5DE5;&#x5382;&#xFF0C;&#x5E76;&#x4E14;&#x901A;&#x8FC7;bean&#x5DE5;&#x5382;&#x83B7;&#x53D6;&#x6240;&#x6709;&#x7684;Advisors</span></span><br><span class="line">    MetadataAwareAspectInstanceFactory factory = <span class="keyword">this</span>.aspectFactoryCache.get(aspectName);</span><br><span class="line">    advisors.addAll(<span class="keyword">this</span>.advisorFactory.getAdvisors(factory));</span><br><span class="line">  }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> advisors;</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x4EE5;&#x4E0A;&#x4EE3;&#x7801;&#x57FA;&#x672C;&#x63CF;&#x8FF0;&#x7684;&#x5C31;&#x662F;&#x904D;&#x5386;&#x5BB9;&#x5668;&#x5185;&#x7684;&#x6240;&#x6709;&#x5BF9;&#x8C61;&#xFF0C;&#x5E76;&#x4E14;&#x5224;&#x65AD;&#x5BF9;&#x8C61;&#x662F;&#x5426;&#x662F;Aspect&#x7C7B;&#x578B;&#xFF0C;&#x5982;&#x679C;&#x662F;&#x7684;&#x8BDD;&#x52A0;&#x5165;&#x5230;Advisors&#x5217;&#x8868;&#x5185;&#xFF0C;&#x5E76;&#x8FD4;&#x56DE;&#x3002;&#x5177;&#x4F53;&#x5224;&#x65AD;&#x903B;&#x8F91;&#x5982;&#x4E0B;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5224;&#x65AD;&#x662F;&#x5426;&#x6709;@Aspect&#x7684;&#x6CE8;&#x89E3;&#x6216;&#x8005;&#x8FD9;&#x4E2A;&#x7C7B;&#x7684;&#x5B57;&#x6BB5;&#x540D;&#x79F0;&#x5B58;&#x5728;`ajc$`&#x524D;&#x7F00;&#xFF08;&#x5982;&#x679C;&#x88AB;AspectJ Compiler&#x7F16;&#x8BD1;&#x7684;&#x7C7B;&#x4F1A;&#x5E26;&#x6709;&#x8FD9;&#x4E2A;&#x524D;&#x7F00;&#xFF09;</span></span><br><span class="line"><span class="keyword">return</span> (hasAspectAnnotation(clazz) &amp;&amp; !compiledByAjc(clazz));</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x83B7;&#x53D6;&#x4E86;&#x6240;&#x6709;&#x7684;Advisors&#x4E4B;&#x540E;&#xFF0C;&#x9700;&#x8981;&#x5224;&#x65AD;&#x5217;&#x8868;&#x662F;&#x5426;&#x4E0D;&#x4E3A;&#x7A7A;&#xFF0C;&#x5373;<code>specificInterceptors != DO_NOT_PROXY</code>&#x3002;</p><p>&#x5982;&#x679C;&#x4E0D;&#x4E3A;&#x7A7A;&#xFF0C;&#x5219;&#x521B;&#x5EFA;&#x5177;&#x4F53;&#x7684;&#x4EE3;&#x7406;&#x7C7B;&#x3002;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5C06;&#x6B64;advisor&#x5B58;&#x5165;advisedBeans&#x7F13;&#x5B58;</span></span><br><span class="line"><span class="keyword">this</span>.advisedBeans.put(cacheKey, Boolean.TRUE);</span><br><span class="line"><span class="comment">// &#x521B;&#x5EFA;&#x4EE3;&#x7406;&#x5BF9;&#x8C61;</span></span><br><span class="line">Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, <span class="keyword">new</span> SingletonTargetSource(bean));</span><br><span class="line"><span class="comment">// &#x7F13;&#x5B58;&#x4EE3;&#x7406;&#x7C7B;&#x7684;&#x7C7B;&#x578B;&#xFF0C;&#x5B58;&#x5165;proxyTypes&#x7F13;&#x5B58;</span></span><br><span class="line"><span class="keyword">this</span>.proxyTypes.put(cacheKey, proxy.getClass());</span><br><span class="line"><span class="keyword">return</span> proxy;</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x5148;&#x770B;&#x4E0B;&#x4EE3;&#x7406;&#x7C7B;&#x7684;&#x5177;&#x4F53;&#x521B;&#x5EFA;&#x903B;&#x8F91;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">protected</span> Object <span class="title">createProxy</span><span class="params">(Class&lt;?&gt; beanClass, @Nullable String beanName,</span></span></span><br><span class="line"><span class="function"><span class="params">@Nullable Object[] specificInterceptors, TargetSource targetSource)</span> </span>{</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// &#x5982;&#x679C;bean&#x5DE5;&#x5382;&#x662F;ConfigurableListableBeanFactory&#x7684;&#x5B9E;&#x4F8B;&#xFF0C;&#x5219;&#x6807;&#x8BB0;exposeTargetClass&#x5C5E;&#x6027;</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">this</span>.beanFactory <span class="keyword">instanceof</span> ConfigurableListableBeanFactory) {</span><br><span class="line">    AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) <span class="keyword">this</span>.beanFactory, beanName, beanClass);</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  ProxyFactory proxyFactory = <span class="keyword">new</span> ProxyFactory();</span><br><span class="line">  proxyFactory.copyFrom(<span class="keyword">this</span>);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x5224;&#x65AD;AspectJ&#x6709;&#x6CA1;&#x6709;&#x8BBE;&#x7F6E;proxyTargetClass&#x5C5E;&#x6027;&#xFF08;&#x4EE3;&#x7406;&#x7C7B;&#x76F4;&#x63A5;&#x7EE7;&#x627F;&#x76EE;&#x6807;&#x7C7B;&#xFF09;</span></span><br><span class="line">  <span class="keyword">if</span> (!proxyFactory.isProxyTargetClass()) {</span><br><span class="line">    <span class="keyword">if</span> (shouldProxyTargetClass(beanClass, beanName)) {</span><br><span class="line">      proxyFactory.setProxyTargetClass(<span class="keyword">true</span>);</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">else</span> {</span><br><span class="line">      evaluateProxyInterfaces(beanClass, proxyFactory);</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x6784;&#x5EFA;&#x5207;&#x9762;</span></span><br><span class="line">  <span class="comment">// &#x5BF9;&#x6240;&#x6709;&#x7684;&#x5207;&#x9762;&#xFF08;common&#x3001;advisor&#x3001;advice&#xFF09;&#x505A;&#x4E00;&#x6B21;&#x5C01;&#x88C5;&#xFF0C;&#x5C06;&#x4E4B;&#x5168;&#x90E8;&#x5206;&#x88C5;&#x4E3A;Advisor&#x7C7B;&#x578B;</span></span><br><span class="line">  Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);</span><br><span class="line">  proxyFactory.addAdvisors(advisors);</span><br><span class="line">  <span class="comment">// &#x8BBE;&#x7F6E;&#x4EE3;&#x7406;&#x76EE;&#x6807;&#x7C7B;</span></span><br><span class="line">  proxyFactory.setTargetSource(targetSource);</span><br><span class="line">  <span class="comment">// &#x5B50;&#x7C7B;&#x56DE;&#x8C03;&#xFF0C;&#x76EE;&#x524D;AnnotationAwareAspectJAutoProxyCreator&#x672A;&#x8986;&#x76D6;&#x8BE5;&#x65B9;&#x6CD5;&#xFF0C;&#x5FFD;&#x7565;</span></span><br><span class="line">  customizeProxyFactory(proxyFactory);</span><br><span class="line"></span><br><span class="line">  proxyFactory.setFrozen(<span class="keyword">this</span>.freezeProxy);</span><br><span class="line">  <span class="keyword">if</span> (advisorsPreFiltered()) {</span><br><span class="line">    proxyFactory.setPreFiltered(<span class="keyword">true</span>);</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x83B7;&#x53D6;&#x4EE3;&#x7406;&#x7C7B;</span></span><br><span class="line">  <span class="keyword">return</span> proxyFactory.getProxy(getProxyClassLoader());</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x63A5;&#x4E0B;&#x6765;&#x5C31;&#x662F;&#x901A;&#x8FC7;&#x4EE3;&#x7406;&#x5DE5;&#x5382;&#x6765;&#x5177;&#x4F53;&#x521B;&#x5EFA;&#x4EE3;&#x7406;&#x7C7B;&#xFF0C;Spring&#x4E2D;&#xFF0C;&#x53EF;&#x4EE5;&#x901A;&#x8FC7;&#x4E24;&#x79CD;&#x65B9;&#x5F0F;&#x6765;&#x521B;&#x5EFA;&#x4EE3;&#x7406;&#x7C7B;&#xFF1A;</p><ul><li>Jdk&#x52A8;&#x6001;&#x4EE3;&#x7406;</li><li>Cglib&#x52A8;&#x6001;&#x4EE3;&#x7406;</li></ul><p>&#x5177;&#x4F53;&#x4F7F;&#x7528;&#x54EA;&#x79CD;&#x65B9;&#x5F0F;&#x7684;&#x901A;&#x8FC7;&#x5982;&#x4E0B;&#x6761;&#x4EF6;&#x5224;&#x65AD;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x672A;&#x914D;&#x7F6E;&#x4F18;&#x5316;&#x4E14;&#x672A;&#x8BBE;&#x7F6E;proxyTargetClass&#x4E3A;true&#x4E14;&#x6709;&#x7528;&#x6237;&#x81EA;&#x5B9A;&#x4E49;&#x7684;&#x4EE3;&#x7406;&#x63A5;&#x53E3;&#xFF0C;&#x5219;&#x76F4;&#x63A5;&#x4F7F;&#x7528;JDK&#x52A8;&#x6001;&#x4EE3;&#x7406;</span></span><br><span class="line"><span class="keyword">if</span> (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {</span><br><span class="line">  Class&lt;?&gt; targetClass = config.getTargetClass();</span><br><span class="line">  <span class="keyword">if</span> (targetClass == <span class="keyword">null</span>) {</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> AopConfigException(<span class="string">&quot;TargetSource cannot determine target class: &quot;</span> +</span><br><span class="line">        <span class="string">&quot;Either an interface or a target is required for proxy creation.&quot;</span>);</span><br><span class="line">  }</span><br><span class="line">  <span class="comment">// &#x76EE;&#x6807;&#x4EE3;&#x7406;&#x7C7B;&#x4E3A;&#x63A5;&#x53E3;&#x6216;&#x8005;&#x662F;&#x4EE3;&#x7406;&#x7C7B;&#xFF0C;&#x5219;&#x4F7F;&#x7528;JDK&#x52A8;&#x6001;&#x4EE3;&#x7406;</span></span><br><span class="line">  <span class="keyword">if</span> (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> JdkDynamicAopProxy(config);</span><br><span class="line">  }</span><br><span class="line">  <span class="comment">// &#x5176;&#x4ED6;&#x60C5;&#x51B5;&#x4F7F;&#x7528;Cglib&#x52A8;&#x6001;&#x4EE3;&#x7406;</span></span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> ObjenesisCglibAopProxy(config);</span><br><span class="line">}</span><br><span class="line"><span class="keyword">else</span> {</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> JdkDynamicAopProxy(config);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x5728;&#x8FD9;&#x91CC;&#xFF0C;&#x5BF9;JDK&#x52A8;&#x6001;&#x4EE3;&#x7406;&#x4E0D;&#x505A;&#x5177;&#x4F53;&#x5206;&#x6790;&#xFF0C;&#x5177;&#x4F53;&#x6765;&#x770B;<code>ObjenesisCglibAopProxy</code>&#x7C7B;&#x5185;<code>getProxy</code>&#x7684;&#x83B7;&#x53D6;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (logger.isDebugEnabled()) {</span><br><span class="line">  logger.debug(<span class="string">&quot;Creating CGLIB proxy: target source is &quot;</span> + <span class="keyword">this</span>.advised.getTargetSource());</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line">  Class&lt;?&gt; rootClass = <span class="keyword">this</span>.advised.getTargetClass();</span><br><span class="line">  Assert.state(rootClass != <span class="keyword">null</span>, <span class="string">&quot;Target class must be available for creating a CGLIB proxy&quot;</span>);</span><br><span class="line"></span><br><span class="line">  Class&lt;?&gt; proxySuperClass = rootClass;</span><br><span class="line">  <span class="keyword">if</span> (ClassUtils.isCglibProxyClass(rootClass)) {</span><br><span class="line">    proxySuperClass = rootClass.getSuperclass();</span><br><span class="line">    Class&lt;?&gt;[] additionalInterfaces = rootClass.getInterfaces();</span><br><span class="line">    <span class="keyword">for</span> (Class&lt;?&gt; additionalInterface : additionalInterfaces) {</span><br><span class="line">      <span class="keyword">this</span>.advised.addInterface(additionalInterface);</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Validate the class, writing log messages as necessary.</span></span><br><span class="line">  validateClassIfNecessary(proxySuperClass, classLoader);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Configure CGLIB Enhancer...</span></span><br><span class="line">  Enhancer enhancer = createEnhancer();</span><br><span class="line">  <span class="keyword">if</span> (classLoader != <span class="keyword">null</span>) {</span><br><span class="line">    enhancer.setClassLoader(classLoader);</span><br><span class="line">    <span class="keyword">if</span> (classLoader <span class="keyword">instanceof</span> SmartClassLoader &amp;&amp;</span><br><span class="line">        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {</span><br><span class="line">      enhancer.setUseCache(<span class="keyword">false</span>);</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line">  enhancer.setSuperclass(proxySuperClass);</span><br><span class="line">  enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(<span class="keyword">this</span>.advised));</span><br><span class="line">  enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);</span><br><span class="line">  enhancer.setStrategy(<span class="keyword">new</span> ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x83B7;&#x53D6;&#x56DE;&#x8C03;&#x65B9;&#x6CD5;&#xFF08;&#x5176;&#x4E2D;&#x5305;&#x62EC;&#x6700;&#x91CD;&#x8981;&#x7684;aopInterceptor&#xFF0C;&#x7528;&#x4E8E;advices&#x8C03;&#x7528;&#x94FE;&#x7684;&#x5904;&#x7406;&#xFF09;</span></span><br><span class="line">  Callback[] callbacks = getCallbacks(rootClass);</span><br><span class="line">  Class&lt;?&gt;[] types = <span class="keyword">new</span> Class&lt;?&gt;[callbacks.length];</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">int</span> x = <span class="number">0</span>; x &lt; types.length; x++) {</span><br><span class="line">    types[x] = callbacks[x].getClass();</span><br><span class="line">  }</span><br><span class="line">  <span class="comment">// fixedInterceptorMap only populated at this point, after getCallbacks call above</span></span><br><span class="line">  enhancer.setCallbackFilter(<span class="keyword">new</span> ProxyCallbackFilter(</span><br><span class="line">      <span class="keyword">this</span>.advised.getConfigurationOnlyCopy(), <span class="keyword">this</span>.fixedInterceptorMap, <span class="keyword">this</span>.fixedInterceptorOffset));</span><br><span class="line">  enhancer.setCallbackTypes(types);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// &#x751F;&#x6210;&#x4EE3;&#x7406;class&#x548C;&#x4EE3;&#x7406;&#x5B9E;&#x4F8B;</span></span><br><span class="line">  <span class="keyword">return</span> createProxyClassAndInstance(enhancer, callbacks);</span><br><span class="line">}</span><br><span class="line"><span class="keyword">catch</span> (CodeGenerationException | IllegalArgumentException ex) {</span><br><span class="line">  <span class="keyword">throw</span> <span class="keyword">new</span> AopConfigException(<span class="string">&quot;Could not generate CGLIB subclass of &quot;</span> + <span class="keyword">this</span>.advised.getTargetClass() +</span><br><span class="line">      <span class="string">&quot;: Common causes of this problem include using a final class or a non-visible class&quot;</span>,</span><br><span class="line">      ex);</span><br><span class="line">}</span><br><span class="line"><span class="keyword">catch</span> (Throwable ex) {</span><br><span class="line">  <span class="comment">// TargetSource.getTarget() failed</span></span><br><span class="line">  <span class="keyword">throw</span> <span class="keyword">new</span> AopConfigException(<span class="string">&quot;Unexpected AOP exception&quot;</span>, ex);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><h3 id="AOP-advice&#x7684;&#x987A;&#x5E8F;&#x95EE;&#x9898;"><a href="#AOP-advice&#x7684;&#x987A;&#x5E8F;&#x95EE;&#x9898;" class="headerlink" title="AOP advice&#x7684;&#x987A;&#x5E8F;&#x95EE;&#x9898;"></a>AOP advice&#x7684;&#x987A;&#x5E8F;&#x95EE;&#x9898;</h3><p>&#x5176;&#x5B9E;&#x5728;&#x901A;&#x8FC7;<code>AbstractAutoProxyCreator</code>&#x7C7B;&#x7684;<code>findCandidateAdvisors</code>&#x65B9;&#x6CD5;&#x83B7;&#x53D6;&#x6240;&#x6709;&#x7684;advice&#x540E;&#xFF0C;&#x4F1A;&#x5BF9;&#x8FD9;&#x4E9B;advice&#x505A;&#x4E00;&#x4E2A;&#x6392;&#x5E8F;&#x5904;&#x7406;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (!eligibleAdvisors.isEmpty()) {</span><br><span class="line">  eligibleAdvisors = sortAdvisors(eligibleAdvisors);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>Advisors&#x7684;&#x6392;&#x5E8F;&#x5B9E;&#x73B0;&#x662F;&#x901A;&#x8FC7;<code>AnnotationAwareOrderComparator</code>&#x7C7B;&#x6765;&#x8FBE;&#x6210;&#x7684;&#x3002;&#x8FD9;&#x4E2A;&#x7C7B;&#x7EE7;&#x627F;&#x4E86;<code>OrderComparator</code>&#x7C7B;&#xFF0C;&#x8986;&#x76D6;&#x4E86;<code>findOrder</code>&#x548C;<code>getPriority</code>&#x65B9;&#x6CD5;&#x3002;</p><p>&#x5176;&#x5185;&#x90E8;&#x5B9E;&#x73B0;&#x7684;&#x987A;&#x5E8F;&#x4E3A;&#xFF1A;Ordered&#x63A5;&#x53E3; -&gt; &#x7C7B;&#x7EA7;&#x522B;&#x7684;Order -&gt; &#x7C7B;&#x7EA7;&#x522B;&#x7684;Prority -&gt; &#x5176;&#x4ED6;&#x88AB;&#x6CE8;&#x89E3;&#x5143;&#x7D20;&#x7684;Order -&gt; &#x5176;&#x4ED6;&#x88AB;&#x6CE8;&#x89E3;&#x5143;&#x7D20;&#x7684;Prority&#x3002;</p><h3 id="AOP-advice&#x7684;&#x5177;&#x4F53;&#x8C03;&#x7528;"><a href="#AOP-advice&#x7684;&#x5177;&#x4F53;&#x8C03;&#x7528;" class="headerlink" title="AOP advice&#x7684;&#x5177;&#x4F53;&#x8C03;&#x7528;"></a>AOP advice&#x7684;&#x5177;&#x4F53;&#x8C03;&#x7528;</h3><p>Spring AOP&#x7684;&#x5B9E;&#x73B0;&#x5E76;&#x4E0D;&#x662F;&#x5C06;&#x6240;&#x6709;&#x7684;advice&#x786C;&#x7F16;&#x7801;&#x8FDB;&#x76EE;&#x6807;&#x4EE3;&#x7406;&#x7C7B;&#xFF0C;&#x800C;&#x662F;&#x901A;&#x8FC7;&#x7EC7;&#x5165;<code>DynamicAdvisedInterceptor</code>&#x7C7B;&#xFF0C;&#x5728;<code>intercept</code>&#x65B9;&#x6CD5;&#x5185;&#x90E8;&#x8C03;&#x7528;advice&#x8C03;&#x7528;&#x94FE;&#x6765;&#x8FBE;&#x5230;&#x62E6;&#x622A;&#x7684;&#x76EE;&#x7684;&#x3002;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> Object <span class="title">intercept</span><span class="params">(Object proxy, Method method, Object[] args, MethodProxy methodProxy)</span> <span class="keyword">throws</span> Throwable </span>{</span><br><span class="line">  Object oldProxy = <span class="keyword">null</span>;</span><br><span class="line">  <span class="keyword">boolean</span> setProxyContext = <span class="keyword">false</span>;</span><br><span class="line">  Object target = <span class="keyword">null</span>;</span><br><span class="line">  TargetSource targetSource = <span class="keyword">this</span>.advised.getTargetSource();</span><br><span class="line">  <span class="keyword">try</span> {</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">this</span>.advised.exposeProxy) {</span><br><span class="line">      <span class="comment">// Make invocation available if necessary.</span></span><br><span class="line">      oldProxy = AopContext.setCurrentProxy(proxy);</span><br><span class="line">      setProxyContext = <span class="keyword">true</span>;</span><br><span class="line">    }</span><br><span class="line">    <span class="comment">// Get as late as possible to minimize the time we &quot;own&quot; the target, in case it comes from a pool...</span></span><br><span class="line">    target = targetSource.getTarget();</span><br><span class="line">    Class&lt;?&gt; targetClass = (target != <span class="keyword">null</span> ? target.getClass() : <span class="keyword">null</span>);</span><br><span class="line">    <span class="comment">// &#x901A;&#x8FC7;&#x62E6;&#x622A;&#x7684;&#x65B9;&#x6CD5;&#x548C;&#x76EE;&#x6807;&#x5BF9;&#x8C61;&#xFF0C;&#x83B7;&#x53D6;&#x8BE5;&#x65B9;&#x6CD5;&#x7684;&#x62E6;&#x622A;&#x8C03;&#x7528;&#x94FE;</span></span><br><span class="line">    List&lt;Object&gt; chain = <span class="keyword">this</span>.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);</span><br><span class="line">    Object retVal;</span><br><span class="line">    <span class="comment">// Check whether we only have one InvokerInterceptor: that is,</span></span><br><span class="line">    <span class="comment">// no real advice, but just reflective invocation of the target.</span></span><br><span class="line">    <span class="keyword">if</span> (chain.isEmpty() &amp;&amp; Modifier.isPublic(method.getModifiers())) {</span><br><span class="line">      <span class="comment">// We can skip creating a MethodInvocation: just invoke the target directly.</span></span><br><span class="line">      <span class="comment">// Note that the final invoker must be an InvokerInterceptor, so we know</span></span><br><span class="line">      <span class="comment">// it does nothing but a reflective operation on the target, and no hot</span></span><br><span class="line">      <span class="comment">// swapping or fancy proxying.</span></span><br><span class="line">      Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);</span><br><span class="line">      retVal = methodProxy.invoke(target, argsToUse);</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">else</span> {</span><br><span class="line">      <span class="comment">// We need to create a method invocation...</span></span><br><span class="line">      <span class="comment">// &#x5982;&#x679C;&#x5B58;&#x5728;&#x8C03;&#x7528;&#x94FE;&#xFF0C;&#x5219;&#x5B9E;&#x4F8B;&#x5316;&#x4E00;&#x4E2A;CglibMethodInvocation&#x7C7B;&#xFF0C;&#x5E76;&#x6267;&#x884C;&#x83B7;&#x5F97;&#x8FD4;&#x56DE;&#x503C;</span></span><br><span class="line">      retVal = <span class="keyword">new</span> CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();</span><br><span class="line">    }</span><br><span class="line">    retVal = processReturnType(proxy, target, method, retVal);</span><br><span class="line">    <span class="keyword">return</span> retVal;</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">finally</span> {</span><br><span class="line">    <span class="keyword">if</span> (target != <span class="keyword">null</span> &amp;&amp; !targetSource.isStatic()) {</span><br><span class="line">      targetSource.releaseTarget(target);</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">if</span> (setProxyContext) {</span><br><span class="line">      <span class="comment">// Restore old proxy.</span></span><br><span class="line">      AopContext.setCurrentProxy(oldProxy);</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x63A5;&#x4E0B;&#x6765;&#x770B;&#x4E0B;<code>CglibMethodInvocation</code>&#x7684;<code>proceed</code>&#x65B9;&#x6CD5;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//We start with an index of -1 and increment early.</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">this</span>.currentInterceptorIndex == <span class="keyword">this</span>.interceptorsAndDynamicMethodMatchers.size() - <span class="number">1</span>) {</span><br><span class="line">  <span class="comment">// &#x5982;&#x679C;&#x8C03;&#x7528;&#x94FE;&#x5168;&#x90E8;&#x6267;&#x884C;&#x5B8C;&#x6BD5;&#xFF0C;&#x5219;&#x6267;&#x884C;&#x88AB;&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x7684;&#x539F;&#x65B9;&#x6CD5;</span></span><br><span class="line">  <span class="keyword">return</span> invokeJoinpoint();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// &#x83B7;&#x5F97;&#x672C;&#x6B21;&#x7684;advice</span></span><br><span class="line">Object interceptorOrInterceptionAdvice =</span><br><span class="line">    <span class="keyword">this</span>.interceptorsAndDynamicMethodMatchers.get(++<span class="keyword">this</span>.currentInterceptorIndex);</span><br><span class="line"><span class="keyword">if</span> (interceptorOrInterceptionAdvice <span class="keyword">instanceof</span> InterceptorAndDynamicMethodMatcher) {</span><br><span class="line">  <span class="comment">// Evaluate dynamic method matcher here: static part will already have</span></span><br><span class="line">  <span class="comment">// been evaluated and found to match.</span></span><br><span class="line">  InterceptorAndDynamicMethodMatcher dm =</span><br><span class="line">      (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;</span><br><span class="line">  <span class="keyword">if</span> (dm.methodMatcher.matches(<span class="keyword">this</span>.method, <span class="keyword">this</span>.targetClass, <span class="keyword">this</span>.arguments)) {</span><br><span class="line">    <span class="keyword">return</span> dm.interceptor.invoke(<span class="keyword">this</span>);</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">else</span> {</span><br><span class="line">    <span class="comment">// Dynamic matching failed.</span></span><br><span class="line">    <span class="comment">// Skip this interceptor and invoke the next in the chain.</span></span><br><span class="line">    <span class="keyword">return</span> proceed();</span><br><span class="line">  }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">else</span> {</span><br><span class="line">  <span class="comment">// It&apos;s an interceptor, so we just invoke it: The pointcut will have</span></span><br><span class="line">  <span class="comment">// been evaluated statically before this object was constructed.</span></span><br><span class="line">  <span class="comment">// &#x7EE7;&#x7EED;&#x6267;&#x884C;&#x4E0B;&#x4E00;&#x4E2A;&#x62E6;&#x622A;&#x5668;</span></span><br><span class="line">  <span class="keyword">return</span> ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(<span class="keyword">this</span>);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x62E6;&#x622A;&#x5668;&#x7684;&#x6267;&#x884C;&#x987A;&#x5E8F;&#xFF0C;&#x662F;&#x6839;&#x636E;&#x8C03;&#x7528;&#x94FE;&#x7684;&#x987A;&#x5E8F;&#x6765;&#x6267;&#x884C;&#x7684;&#xFF0C;&#x800C;&#x8C03;&#x7528;&#x94FE;&#x7684;&#x987A;&#x5E8F;&#x65E9;&#x5728;&#x4E4B;&#x524D;&#x7684;sort&#x9636;&#x6BB5;&#x5C31;&#x5DF2;&#x7ECF;&#x6392;&#x5217;&#x597D;&#x4E86;&#xFF1B;&#x5982;&#x4E0B;&#x7684;&#x4EE3;&#x7801;&#x4E3B;&#x8981;&#x662F;&#x83B7;&#x53D6;&#x76EE;&#x6807;&#x5BF9;&#x8C61;&#x548C;&#x65B9;&#x6CD5;&#x5BF9;&#x5E94;&#x7684;&#x62E6;&#x622A;&#x5668;&#x94FE;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> List&lt;Object&gt; <span class="title">getInterceptorsAndDynamicInterceptionAdvice</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">Advised config, Method method, @Nullable Class&lt;?&gt; targetClass)</span> </span>{</span><br><span class="line"></span><br><span class="line">  <span class="comment">// This is somewhat tricky... We have to process introductions first,</span></span><br><span class="line">  <span class="comment">// but we need to preserve order in the ultimate list.</span></span><br><span class="line">  List&lt;Object&gt; interceptorList = <span class="keyword">new</span> ArrayList&lt;Object&gt;(config.getAdvisors().length);</span><br><span class="line">  Class&lt;?&gt; actualClass = (targetClass != <span class="keyword">null</span> ? targetClass : method.getDeclaringClass());</span><br><span class="line">  <span class="keyword">boolean</span> hasIntroductions = hasMatchingIntroductions(config, actualClass);</span><br><span class="line">  AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> (Advisor advisor : config.getAdvisors()) {</span><br><span class="line">    <span class="keyword">if</span> (advisor <span class="keyword">instanceof</span> PointcutAdvisor) {</span><br><span class="line">      <span class="comment">// Add it conditionally.</span></span><br><span class="line">      PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;</span><br><span class="line">      <span class="keyword">if</span> (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {</span><br><span class="line">        MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();</span><br><span class="line">        <span class="keyword">if</span> (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {</span><br><span class="line">          MethodInterceptor[] interceptors = registry.getInterceptors(advisor);</span><br><span class="line">          <span class="keyword">if</span> (mm.isRuntime()) {</span><br><span class="line">            <span class="comment">// Creating a new object instance in the getInterceptors() method</span></span><br><span class="line">            <span class="comment">// isn&apos;t a problem as we normally cache created chains.</span></span><br><span class="line">            <span class="keyword">for</span> (MethodInterceptor interceptor : interceptors) {</span><br><span class="line">              interceptorList.add(<span class="keyword">new</span> InterceptorAndDynamicMethodMatcher(interceptor, mm));</span><br><span class="line">            }</span><br><span class="line">          }</span><br><span class="line">          <span class="keyword">else</span> {</span><br><span class="line">            interceptorList.addAll(Arrays.asList(interceptors));</span><br><span class="line">          }</span><br><span class="line">        }</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (advisor <span class="keyword">instanceof</span> IntroductionAdvisor) {</span><br><span class="line">      IntroductionAdvisor ia = (IntroductionAdvisor) advisor;</span><br><span class="line">      <span class="keyword">if</span> (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {</span><br><span class="line">        Interceptor[] interceptors = registry.getInterceptors(advisor);</span><br><span class="line">        interceptorList.addAll(Arrays.asList(interceptors));</span><br><span class="line">      }</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">else</span> {</span><br><span class="line">      Interceptor[] interceptors = registry.getInterceptors(advisor);</span><br><span class="line">      interceptorList.addAll(Arrays.asList(interceptors));</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> interceptorList;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x4E3E;&#x4E2A;&#x4F8B;&#x5B50;&#xFF0C;&#x58F0;&#x660E;&#x62E6;&#x622A;&#x76EE;&#x6807;&#x7C7B;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Hello</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">world</span><span class="params">()</span> </span>{</span><br><span class="line">        System.out.println(<span class="string">&quot;hello world&quot;</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x5B9A;&#x4E49;&#x4E24;&#x4E2A;&#x62E6;&#x622A;&#x5668;HelloAop&#x4EE5;&#x53CA;HelloAop2&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HelloAop</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Pointcut</span>(<span class="string">&quot;execution(* com.whatakitty.learn.Hello.*(..))&quot;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">world</span><span class="params">()</span> </span>{</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Before</span>(<span class="string">&quot;world()&quot;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">()</span> </span>{</span><br><span class="line">        System.out.println(<span class="string">&quot;start hello world&quot;</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@After</span>(<span class="string">&quot;world()&quot;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">()</span> </span>{</span><br><span class="line">        System.out.println(<span class="string">&quot;end hello world&quot;</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Around</span>(<span class="string">&quot;world()&quot;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">around</span><span class="params">(ProceedingJoinPoint proceedingJoinPoint)</span> </span>{</span><br><span class="line">        System.out.println(<span class="string">&quot;around 1&quot;</span>);</span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            proceedingJoinPoint.proceed();</span><br><span class="line">        } <span class="keyword">catch</span> (Throwable throwable) {</span><br><span class="line">            throwable.printStackTrace();</span><br><span class="line">        }</span><br><span class="line">        System.out.println(<span class="string">&quot;around 1&quot;</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HelloAop2</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Pointcut</span>(<span class="string">&quot;execution(* com.whatakitty.learn.Hello.*(..))&quot;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">world</span><span class="params">()</span> </span>{</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Before</span>(<span class="string">&quot;world()&quot;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">()</span> </span>{</span><br><span class="line">        System.out.println(<span class="string">&quot;start hello world 2&quot;</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@After</span>(<span class="string">&quot;world()&quot;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">after</span><span class="params">()</span> </span>{</span><br><span class="line">        System.out.println(<span class="string">&quot;end hello world 2&quot;</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Around</span>(<span class="string">&quot;world()&quot;</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">around</span><span class="params">(ProceedingJoinPoint proceedingJoinPoint)</span> </span>{</span><br><span class="line">        System.out.println(<span class="string">&quot;around 2&quot;</span>);</span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            proceedingJoinPoint.proceed();</span><br><span class="line">        } <span class="keyword">catch</span> (Throwable throwable) {</span><br><span class="line">            throwable.printStackTrace();</span><br><span class="line">        }</span><br><span class="line">        System.out.println(<span class="string">&quot;around 2&quot;</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x6267;&#x884C;&#x7ED3;&#x679C;&#x5982;&#x4E0B;&#xFF1A;<br></p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">around 1</span><br><span class="line">start hello world</span><br><span class="line">around 2</span><br><span class="line">start hello world 2</span><br><span class="line">hello world</span><br><span class="line">around 2</span><br><span class="line">end hello world 2</span><br><span class="line">around 1</span><br><span class="line">end hello world</span><br></pre></td></tr></tbody></table></figure><p></p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;前提&quot;&gt;&lt;a href=&quot;#前提&quot; class=&quot;headerlink&quot; title=&quot;前提&quot;&gt;&lt;/a&gt;前提&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Spring 5&lt;/li&gt;&lt;li&gt;基于Java Configuration配置，而非XML配置&lt;/li&gt;&lt;li&gt;对于AspectJ的分析，不对Spring本身的Advisor做分析&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;概要&quot;&gt;&lt;a href=&quot;#概要&quot; class=&quot;headerlink&quot; title=&quot;概要&quot;&gt;&lt;/a&gt;概要&lt;/h3&gt;&lt;p&gt;如果需要了解多个AscpectJ对同一个对象操作产生的实际效果以及作用顺序，则需要首先了解AOP对象的构建过程，以及如何织入，还有就是织入过程中的顺序逻辑的了解。&lt;/p&gt;&lt;p&gt;所以，这篇文章主要内容如下：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#AOP构造者注册&quot;&gt;AOP构造者注册&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#AOP代理对象的初始化构建&quot;&gt;AOP代理对象的初始化构建&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#AOP%20advice的顺序问题&quot;&gt;AOP advice的顺序问题&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#AOP%20advice的具体调用&quot;&gt;AOP advice的具体调用&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="Spring" scheme="https://xuqiang.me/categories/Java/Spring/"/>
    
      <category term="SpringSources" scheme="https://xuqiang.me/categories/Java/Spring/SpringSources/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="aop" scheme="https://xuqiang.me/tags/aop/"/>
    
      <category term="spring" scheme="https://xuqiang.me/tags/spring/"/>
    
      <category term="aspectj" scheme="https://xuqiang.me/tags/aspectj/"/>
    
      <category term="cglib" scheme="https://xuqiang.me/tags/cglib/"/>
    
  </entry>
  
  <entry>
    <title>自定义消息队列死锁</title>
    <link href="https://xuqiang.me/%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E6%AD%BB%E9%94%81.html"/>
    <id>https://xuqiang.me/自定义消息队列死锁.html</id>
    <published>2018-08-08T16:21:43.000Z</published>
    <updated>2018-08-20T15:20:52.899Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x6700;&#x8FD1;&#x5728;&#x770B;AQS&#x5E76;&#x53D1;&#x6846;&#x67B6;&#x4EE5;&#x53CA;&#x5176;&#x76F8;&#x5173;&#x7684;&#x540C;&#x6B65;&#x5668;/&#x961F;&#x5217;&#x7B49;&#x7B49;&#x3002;&#x7136;&#x540E;&#xFF0C;&#x60F3;&#x4EE5;&#x540C;&#x6B65;&#x5668;&#x6765;&#x5B9E;&#x73B0;&#x4E00;&#x4E2A;&#x53CC;&#x5411;&#x94FE;&#x8868;&#x7684;&#x961F;&#x5217;&#x3002;&#x4F46;&#x662F;&#xFF0C;&#x5728;&#x5B9E;&#x73B0;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x53D1;&#x73B0;&#x4E00;&#x4E2A;&#x95EE;&#x9898;&#xFF1A;put/take&#x7EBF;&#x7A0B;&#x5728;&#x9AD8;&#x5E76;&#x53D1;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#x4E24;&#x8005;&#x963B;&#x585E;&#xFF0C;&#x5982;&#x679C;&#x4FDD;&#x6301;1ms&#x7684;put&#x65F6;&#x95F4;&#x95F4;&#x9694;&#xFF0C;&#x5219;&#x4E0D;&#x4F1A;&#x51FA;&#x73B0;&#x4E0A;&#x8FF0;&#x95EE;&#x9898;&#x3002;</p><a id="more"></a><h3 id="&#x6E90;&#x4EE3;&#x7801;"><a href="#&#x6E90;&#x4EE3;&#x7801;" class="headerlink" title="&#x6E90;&#x4EE3;&#x7801;"></a>&#x6E90;&#x4EE3;&#x7801;</h3><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyQueue</span>&lt;<span class="title">T</span>&gt; </span>{</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> ReentrantLock putLock = <span class="keyword">new</span> ReentrantLock();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Condition notFull = putLock.newCondition();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> ReentrantLock takeLock = <span class="keyword">new</span> ReentrantLock();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Condition notEmpty = takeLock.newCondition();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> Node&lt;T&gt; head;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> Node&lt;T&gt; tail;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5B9E;&#x9645;&#x5927;&#x5C0F;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> AtomicInteger count = <span class="keyword">new</span> AtomicInteger();</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5141;&#x8BB8;&#x7684;&#x5BB9;&#x91CF;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">int</span> capacity;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MyQueue</span><span class="params">(<span class="keyword">int</span> capacity)</span> </span>{</span><br><span class="line">        <span class="keyword">this</span>.capacity = capacity;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> T <span class="title">put</span><span class="params">(T item)</span> <span class="keyword">throws</span> InterruptedException </span>{</span><br><span class="line">        <span class="keyword">assert</span> item != <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">final</span> ReentrantLock putLock = <span class="keyword">this</span>.putLock;</span><br><span class="line">        putLock.lock();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> c = -<span class="number">1</span>;</span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line"></span><br><span class="line">            <span class="comment">// &#x961F;&#x5217;&#x5DF2;&#x6EE1;&#xFF0C;&#x5176;&#x4ED6;&#x7EBF;&#x7A0B;&#x52A0;&#x5165;nextWaiters&#x963B;&#x585E;</span></span><br><span class="line">            <span class="keyword">while</span> (count.get() == capacity) {</span><br><span class="line">                notFull.await();</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">            enqueue(item);</span><br><span class="line">            c = count.getAndIncrement();</span><br><span class="line">            <span class="keyword">if</span> (c + <span class="number">1</span> &lt; capacity) {</span><br><span class="line">                signalNotEmpty();</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            putLock.unlock();</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> item;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> T <span class="title">take</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException </span>{</span><br><span class="line">        takeLock.lock();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> c = -<span class="number">1</span>;</span><br><span class="line">        Node&lt;T&gt; node;</span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line"></span><br><span class="line">            <span class="comment">// &#x961F;&#x5217;&#x4E3A;&#x7A7A;&#xFF0C;&#x5176;&#x4ED6;&#x7EBF;&#x7A0B;&#x52A0;&#x5165;nextWaiters&#x963B;&#x585E;</span></span><br><span class="line">            <span class="keyword">while</span> (count.get() == <span class="number">0</span>) {</span><br><span class="line">                notEmpty.await();</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">            node = dequeue();</span><br><span class="line">            c = count.getAndDecrement();</span><br><span class="line">            <span class="keyword">if</span> (c &gt; <span class="number">1</span>) {</span><br><span class="line">                signalNotFull();</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            takeLock.unlock();</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> node == <span class="keyword">null</span> ? <span class="keyword">null</span> : node.item;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">enqueue</span><span class="params">(T t)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) {</span><br><span class="line">            head = tail = <span class="keyword">new</span> Node&lt;&gt;(t);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// append to tail</span></span><br><span class="line">        Node&lt;T&gt; node = <span class="keyword">new</span> Node&lt;&gt;(t);</span><br><span class="line">        tail.next = node;</span><br><span class="line">        tail = node;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> Node&lt;T&gt; <span class="title">dequeue</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// remove first node from list</span></span><br><span class="line">        Node&lt;T&gt; removed;</span><br><span class="line">        Node&lt;T&gt; next = head.next;</span><br><span class="line">        head.next = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (next != <span class="keyword">null</span>) {</span><br><span class="line">            next.prev = <span class="keyword">null</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        removed = head;</span><br><span class="line">        head = next;</span><br><span class="line">        <span class="keyword">return</span> removed;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">signalNotEmpty</span><span class="params">()</span> </span>{</span><br><span class="line">        takeLock.lock();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            notEmpty.signal();</span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            takeLock.unlock();</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">signalNotFull</span><span class="params">()</span> </span>{</span><br><span class="line">        putLock.lock();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            notFull.signal();</span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            putLock.unlock();</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="class"><span class="keyword">class</span> <span class="title">Node</span>&lt;<span class="title">T</span>&gt; </span>{</span><br><span class="line"></span><br><span class="line">        Node&lt;T&gt; next;</span><br><span class="line">        Node&lt;T&gt; prev;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">final</span> T item;</span><br><span class="line">        Node(T item) {</span><br><span class="line">            <span class="keyword">this</span>.item = item;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException </span>{</span><br><span class="line"></span><br><span class="line">        MyQueue&lt;String&gt; queue = <span class="keyword">new</span> MyQueue&lt;&gt;(<span class="number">20</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">new</span> Thread(() -&gt; {</span><br><span class="line">            <span class="keyword">while</span> (<span class="keyword">true</span>) {</span><br><span class="line">                <span class="keyword">try</span> {</span><br><span class="line">                    String item = queue.take();</span><br><span class="line">                    <span class="keyword">if</span> (item != <span class="keyword">null</span> &amp;&amp; item.trim() != <span class="string">&quot;&quot;</span>) {</span><br><span class="line">                        System.out.println(item);</span><br><span class="line">                    }</span><br><span class="line">                } <span class="keyword">catch</span> (InterruptedException e) {</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }).start();</span><br><span class="line"></span><br><span class="line">        Thread.sleep(<span class="number">1000</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">new</span> Thread(() -&gt; {</span><br><span class="line">            <span class="keyword">try</span> {</span><br><span class="line">                <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">                <span class="keyword">int</span> max = <span class="number">1000000</span>;</span><br><span class="line">                <span class="keyword">while</span> (<span class="keyword">true</span>) {</span><br><span class="line">                    i++;</span><br><span class="line">                    queue.put(String.valueOf(ThreadLocalRandom.current().nextInt(<span class="number">999999999</span>)));</span><br><span class="line">                    <span class="keyword">if</span> (i &gt; max) {</span><br><span class="line">                        System.out.println(<span class="string">&quot;&#x7ED3;&#x675F;&quot;</span> + i);</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">            } <span class="keyword">catch</span> (InterruptedException e) {</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            }</span><br><span class="line">        }).start();</span><br><span class="line"></span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="&#x95EE;&#x9898;&#x5B9A;&#x4F4D;"><a href="#&#x95EE;&#x9898;&#x5B9A;&#x4F4D;" class="headerlink" title="&#x95EE;&#x9898;&#x5B9A;&#x4F4D;"></a>&#x95EE;&#x9898;&#x5B9A;&#x4F4D;</h3><p>&#x4E3A;&#x4E86;&#x67E5;&#x770B;&#x662F;&#x54EA;&#x91CC;&#x51FA;&#x73B0;&#x4E86;&#x963B;&#x585E;&#x7684;&#x60C5;&#x51B5;&#xFF0C;&#x6211;&#x505A;&#x4E86;dump&#x7EBF;&#x7A0B;&#x64CD;&#x4F5C;<br>&#x5982;&#x4E0B;&#x662F;DUMP&#x4FE1;&#x606F;&#xFF1A;<br></p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">&quot;Thread-1@685&quot; prio=5 tid=0xd nid=NA waiting</span><br><span class="line">  java.lang.Thread.State: WAITING</span><br><span class="line">  at sun.misc.Unsafe.park(Unsafe.java:-1)</span><br><span class="line">  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)</span><br><span class="line">  at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)</span><br><span class="line">  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)</span><br><span class="line">  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)</span><br><span class="line">  at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)</span><br><span class="line">  at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)</span><br><span class="line">  at com.whatakitty.learn.collections.MyQueue.signalNotEmpty(MyQueue.java:136)</span><br><span class="line">  at com.whatakitty.learn.collections.MyQueue.put(MyQueue.java:62)</span><br><span class="line">  at com.whatakitty.learn.collections.MyQueue.lambda$main$1(MyQueue.java:193)</span><br><span class="line">  at com.whatakitty.learn.collections.MyQueue$$Lambda$2.1577213552.run(Unknown Source:-1)</span><br><span class="line">  at java.lang.Thread.run(Thread.java:748)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&quot;Thread-0@681&quot; prio=5 tid=0xc nid=NA waiting</span><br><span class="line">  java.lang.Thread.State: WAITING</span><br><span class="line">  at sun.misc.Unsafe.park(Unsafe.java:-1)</span><br><span class="line">  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)</span><br><span class="line">  at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)</span><br><span class="line">  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)</span><br><span class="line">  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)</span><br><span class="line">  at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)</span><br><span class="line">  at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)</span><br><span class="line">  at com.whatakitty.learn.collections.MyQueue.signalNotFull(MyQueue.java:146)</span><br><span class="line">  at com.whatakitty.learn.collections.MyQueue.take(MyQueue.java:91)</span><br><span class="line">  at com.whatakitty.learn.collections.MyQueue.lambda$main$0(MyQueue.java:175)</span><br><span class="line">  at com.whatakitty.learn.collections.MyQueue$$Lambda$1.431687835.run(Unknown Source:-1)</span><br><span class="line">  at java.lang.Thread.run(Thread.java:748)</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x7684;&#x662F;&#xFF0C;&#x4E24;&#x8005;&#x963B;&#x585E;&#x5730;&#x65B9;&#x662F;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">com.whatakitty.learn.collections.MyQueue.signalNotEmpty(MyQueue.java:<span class="number">136</span>)</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x4EE5;&#x53CA;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">com.whatakitty.learn.collections.MyQueue.signalNotFull(MyQueue.java:<span class="number">146</span>)</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x91CC;&#x9762;&#x7684;lock&#x64CD;&#x4F5C;&#xFF0C;&#x90A3;&#x4E48;&#x5FC5;&#x5B9A;&#x662F;&#x4E24;&#x4E2A;&#x7EBF;&#x7A0B;&#x76F8;&#x4E92;&#x6B7B;&#x9501;&#x4E86;&#x3002;</p><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;<code>signalNotEmpty</code>&#x548C;<code>signalNotFull</code>&#x5185;&#x90E8;&#x90FD;&#x6709;&#x52A0;&#x9501;&#x64CD;&#x4F5C;&#x3002;</p><p>&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x5047;&#x8BBE;&#x5982;&#x4E0B;&#x60C5;&#x666F;&#xFF1A;<br>putLock&#x6267;&#x884C;&#x5230;notEmpty.single&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x9700;&#x8981;&#x83B7;&#x53D6;takeLock&#x7684;&#x9501;&#xFF0C;&#x7136;&#x540E;&#x8FD9;&#x4E2A;&#x65F6;&#x5019;&#xFF0C;takeLock&#x6B63;&#x6267;&#x884C;&#x5230;notFull.single&#x4E14;take&#x64CD;&#x4F5C;&#x6240;&#x5728;&#x7EBF;&#x7A0B;&#x6B63;&#x6301;&#x6709;takeLock&#x7684;&#x9501;&#xFF0C;&#x5BFC;&#x81F4;&#x524D;&#x8005;&#x65E0;&#x6CD5;&#x83B7;&#x5F97;&#x9501;&#xFF0C;&#x9020;&#x6210;&#x76F8;&#x4E92;&#x7B49;&#x5F85;&#xFF0C;&#x5F62;&#x6210;&#x6B7B;&#x9501;&#x3002;</p><h3 id="&#x89E3;&#x51B3;&#x95EE;&#x9898;"><a href="#&#x89E3;&#x51B3;&#x95EE;&#x9898;" class="headerlink" title="&#x89E3;&#x51B3;&#x95EE;&#x9898;"></a>&#x89E3;&#x51B3;&#x95EE;&#x9898;</h3><p>&#x95EE;&#x9898;&#x7684;&#x89E3;&#x51B3;&#x601D;&#x8DEF;&#x4E3B;&#x8981;&#x662F;&#x53C2;&#x7167;&#x4E86;LinkedBlockingQueue&#x7684;&#x8BBE;&#x8BA1;&#xFF1B;&#x5728;put&#x64CD;&#x4F5C;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x5982;&#x679C;&#x52A0;&#x5165;&#x4E86;&#x5143;&#x7D20;&#xFF0C;&#x4E14;&#x76EE;&#x524D;&#x961F;&#x5217;&#x7684;&#x5927;&#x5C0F;&#x4E0D;&#x8D85;&#x8FC7;&#x5BB9;&#x91CF;&#xFF0C;&#x5219;&#x505A;notFull&#x7684;&#x901A;&#x77E5;&#xFF0C;&#x4E14;&#x5982;&#x679C;&#x521D;&#x6B21;&#x589E;&#x52A0;&#xFF0C;&#x5219;&#x505A;notEmpty&#x5524;&#x9192;&#xFF0C;&#x8FD9;&#x4E48;&#x505A;&#x4E3B;&#x8981;&#x662F;&#x4E3A;&#x4E86;&#x9632;&#x6B62;take&#x64CD;&#x4F5C;&#x6240;&#x5728;&#x7EBF;&#x7A0B;park&#x7B49;&#x5F85;&#xFF0C;&#x800C;put&#x540E;&#x672A;&#x901A;&#x77E5;&#x9020;&#x6210;&#x963B;&#x585E;&#x7684;&#x60C5;&#x51B5;&#x53D1;&#x751F;&#x3002;</p><p>&#x65B0;&#x7684;&#x4EE3;&#x7801;&#x5982;&#x4E0B;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyQueue</span>&lt;<span class="title">T</span>&gt; </span>{</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> ReentrantLock putLock = <span class="keyword">new</span> ReentrantLock();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Condition notFull = putLock.newCondition();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> ReentrantLock takeLock = <span class="keyword">new</span> ReentrantLock();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Condition notEmpty = takeLock.newCondition();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> Node&lt;T&gt; head;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> Node&lt;T&gt; tail;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5B9E;&#x9645;&#x5927;&#x5C0F;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> AtomicInteger count = <span class="keyword">new</span> AtomicInteger();</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5141;&#x8BB8;&#x7684;&#x5BB9;&#x91CF;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">int</span> capacity;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MyQueue</span><span class="params">(<span class="keyword">int</span> capacity)</span> </span>{</span><br><span class="line">        <span class="keyword">this</span>.capacity = capacity;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> T <span class="title">put</span><span class="params">(T item)</span> <span class="keyword">throws</span> InterruptedException </span>{</span><br><span class="line">        <span class="keyword">assert</span> item != <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">final</span> ReentrantLock putLock = <span class="keyword">this</span>.putLock;</span><br><span class="line">        putLock.lock();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> c = -<span class="number">1</span>;</span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line"></span><br><span class="line">            <span class="comment">// &#x961F;&#x5217;&#x5DF2;&#x6EE1;&#xFF0C;&#x5176;&#x4ED6;&#x7EBF;&#x7A0B;&#x52A0;&#x5165;nextWaiters&#x963B;&#x585E;</span></span><br><span class="line">            <span class="keyword">while</span> (count.get() == capacity) {</span><br><span class="line">                notFull.await();</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">            enqueue(item);</span><br><span class="line">            c = count.getAndIncrement();</span><br><span class="line">            <span class="keyword">if</span> (c + <span class="number">1</span> &lt; capacity) {</span><br><span class="line">                notFull.signal();</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            putLock.unlock();</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &#x5728;&#x961F;&#x5217;&#x589E;&#x52A0;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x540E;&#xFF0C;&#x901A;&#x77E5;take&#x7EBF;&#x7A0B;&#xFF0C;&#x53EF;&#x4EE5;&#x7EE7;&#x7EED;&#x6D88;&#x8D39;&#x4E86;</span></span><br><span class="line">        <span class="keyword">if</span> (c == <span class="number">0</span>) {</span><br><span class="line">            signalNotEmpty();</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> item;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> T <span class="title">take</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException </span>{</span><br><span class="line">        takeLock.lock();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> c = -<span class="number">1</span>;</span><br><span class="line">        Node&lt;T&gt; node;</span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line"></span><br><span class="line">            <span class="comment">// &#x961F;&#x5217;&#x4E3A;&#x7A7A;&#xFF0C;&#x5176;&#x4ED6;&#x7EBF;&#x7A0B;&#x52A0;&#x5165;nextWaiters&#x963B;&#x585E;</span></span><br><span class="line">            <span class="keyword">while</span> (count.get() == <span class="number">0</span>) {</span><br><span class="line">                notEmpty.await();</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">            node = dequeue();</span><br><span class="line">            c = count.getAndDecrement();</span><br><span class="line">            <span class="keyword">if</span> (c &gt; <span class="number">1</span>) {</span><br><span class="line">                <span class="comment">// &#x901A;&#x77E5;take&#x7684;&#x5176;&#x4ED6;&#x7EBF;&#x7A0B;</span></span><br><span class="line">                notEmpty.signal();</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            takeLock.unlock();</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &#x5728;&#x961F;&#x5217;&#x6D88;&#x8D39;&#x4E00;&#x6B21;&#x540E;&#xFF0C;&#x901A;&#x77E5;&#x52A0;&#x5165;&#x5143;&#x7D20;&#x7684;&#x7EBF;&#x7A0B;&#xFF0C;&#x53EF;&#x4EE5;&#x7EE7;&#x7EED;&#x52A0;&#x5165;&#x5143;&#x7D20;&#x4E86;</span></span><br><span class="line">        <span class="keyword">if</span> (c == capacity) {</span><br><span class="line">            signalNotFull();</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> node == <span class="keyword">null</span> ? <span class="keyword">null</span> : node.item;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">enqueue</span><span class="params">(T t)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) {</span><br><span class="line">            head = tail = <span class="keyword">new</span> Node&lt;&gt;(t);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// append to tail</span></span><br><span class="line">        Node&lt;T&gt; node = <span class="keyword">new</span> Node&lt;&gt;(t);</span><br><span class="line">        tail.next = node;</span><br><span class="line">        tail = node;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> Node&lt;T&gt; <span class="title">dequeue</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// remove first node from list</span></span><br><span class="line">        Node&lt;T&gt; removed;</span><br><span class="line">        Node&lt;T&gt; next = head.next;</span><br><span class="line">        head.next = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (next != <span class="keyword">null</span>) {</span><br><span class="line">            next.prev = <span class="keyword">null</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        removed = head;</span><br><span class="line">        head = next;</span><br><span class="line">        <span class="keyword">return</span> removed;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">signalNotEmpty</span><span class="params">()</span> </span>{</span><br><span class="line">        takeLock.lock();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            notEmpty.signal();</span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            takeLock.unlock();</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">signalNotFull</span><span class="params">()</span> </span>{</span><br><span class="line">        putLock.lock();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            notFull.signal();</span><br><span class="line">        } <span class="keyword">finally</span> {</span><br><span class="line">            putLock.unlock();</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="class"><span class="keyword">class</span> <span class="title">Node</span>&lt;<span class="title">T</span>&gt; </span>{</span><br><span class="line"></span><br><span class="line">        Node&lt;T&gt; next;</span><br><span class="line">        Node&lt;T&gt; prev;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">final</span> T item;</span><br><span class="line">        Node(T item) {</span><br><span class="line">            <span class="keyword">this</span>.item = item;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException </span>{</span><br><span class="line"></span><br><span class="line">        MyQueue&lt;String&gt; queue = <span class="keyword">new</span> MyQueue&lt;&gt;(<span class="number">20</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">new</span> Thread(() -&gt; {</span><br><span class="line">            <span class="keyword">try</span> {</span><br><span class="line">                <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">                <span class="keyword">int</span> max = <span class="number">1000000</span>;</span><br><span class="line">                <span class="keyword">while</span> (<span class="keyword">true</span>) {</span><br><span class="line">                    i++;</span><br><span class="line">                    queue.put(String.valueOf(ThreadLocalRandom.current().nextInt(<span class="number">999999999</span>)));</span><br><span class="line">                    <span class="keyword">if</span> (i &gt; max) {</span><br><span class="line">                        System.out.println(<span class="string">&quot;&#x7ED3;&#x675F;&quot;</span> + i);</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">            } <span class="keyword">catch</span> (InterruptedException e) {</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            }</span><br><span class="line">        }).start();</span><br><span class="line"></span><br><span class="line">        Thread.sleep(<span class="number">1000</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">new</span> Thread(() -&gt; {</span><br><span class="line">            <span class="keyword">while</span> (<span class="keyword">true</span>) {</span><br><span class="line">                <span class="keyword">try</span> {</span><br><span class="line">                    String item = queue.take();</span><br><span class="line">                    <span class="keyword">if</span> (item != <span class="keyword">null</span> &amp;&amp; item.trim() != <span class="string">&quot;&quot;</span>) {</span><br><span class="line">                        System.out.println(item);</span><br><span class="line">                    }</span><br><span class="line">                } <span class="keyword">catch</span> (InterruptedException e) {</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }).start();</span><br><span class="line"></span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p></p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;最近在看AQS并发框架以及其相关的同步器/队列等等。然后，想以同步器来实现一个双向链表的队列。但是，在实现过程中，发现一个问题：put/take线程在高并发的情况下两者阻塞，如果保持1ms的put时间间隔，则不会出现上述问题。&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="AQS" scheme="https://xuqiang.me/categories/Java/AQS/"/>
    
      <category term="Queue" scheme="https://xuqiang.me/categories/Java/AQS/Queue/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="aqs" scheme="https://xuqiang.me/tags/aqs/"/>
    
      <category term="condition" scheme="https://xuqiang.me/tags/condition/"/>
    
      <category term="reentrantLock" scheme="https://xuqiang.me/tags/reentrantLock/"/>
    
      <category term="queue" scheme="https://xuqiang.me/tags/queue/"/>
    
  </entry>
  
  <entry>
    <title>ConcurrentHashMap RESERVED状态死循环</title>
    <link href="https://xuqiang.me/ConcurrentHashMap-RESERVED%E7%8A%B6%E6%80%81%E6%AD%BB%E5%BE%AA%E7%8E%AF.html"/>
    <id>https://xuqiang.me/ConcurrentHashMap-RESERVED状态死循环.html</id>
    <published>2018-07-31T16:11:38.000Z</published>
    <updated>2018-07-31T16:14:51.000Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x80CC;&#x666F;"><a href="#&#x80CC;&#x666F;" class="headerlink" title="&#x80CC;&#x666F;"></a>&#x80CC;&#x666F;</h3><p>&#x4ECA;&#x5929;&#x672C;&#x6765;&#x662F;&#x60F3;&#x8981;&#x4F18;&#x5316;&#x4E0B;&#x81EA;&#x5DF1;&#x7684;OTA&#x4EE3;&#x7801;&#xFF0C;&#x4F7F;&#x5F97;&#x6548;&#x7387;&#x66F4;&#x9AD8;&#xFF0C;&#x7ED3;&#x679C;&#x88AB;&#x73B0;&#x5B9E;&#x8D64;&#x88F8;&#x88F8;&#x6253;&#x4E86;&#x8138;&#x3002;</p><a id="more"></a><h3 id="&#x8FC7;&#x7A0B;"><a href="#&#x8FC7;&#x7A0B;" class="headerlink" title="&#x8FC7;&#x7A0B;"></a>&#x8FC7;&#x7A0B;</h3><p>&#x5982;&#x4E0B;&#x662F;&#x539F;&#x5148;&#x7684;&#x4EE3;&#x7801;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Map&lt;String, Object&gt; holder = <span class="keyword">new</span> ConcurrentHashMap&lt;&gt;(<span class="number">16</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (holder.get(clazzName) == <span class="keyword">null</span>) {</span><br><span class="line">    holder.putIfAbsent(clazzName, createSingleton(clazz, params));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> (T) holder.get(clazzName);</span><br></pre></td></tr></tbody></table></figure><p>&#x5982;&#x4E0A;&#x4EE3;&#x7801;&#x662F;&#x7B14;&#x8005;&#x4E00;&#x4E2A;&#x5355;&#x4F8B;&#x521B;&#x5EFA;&#x5DE5;&#x5177;&#x7684;&#x4E00;&#x90E8;&#x5206;&#x4EE3;&#x7801;&#xFF0C;&#x4ECA;&#x5929;&#x5728;&#x6D4F;&#x89C8;<code>Map</code>&#x63A5;&#x53E3;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x53D1;&#x73B0;&#x4E86;&#x51E0;&#x4E2A;&#x65B9;&#x6CD5;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">default</span> V <span class="title">computeIfAbsent</span><span class="params">(K key, Function&lt;? <span class="keyword">super</span> K, ? extends V&gt; mappingFunction)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">default</span> V <span class="title">computeIfPresent</span><span class="params">(K key, BiFunction&lt;? <span class="keyword">super</span> K, ? <span class="keyword">super</span> V, ? extends V&gt; remappingFunction)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">default</span> V <span class="title">compute</span><span class="params">(K key, BiFunction&lt;? <span class="keyword">super</span> K, ? <span class="keyword">super</span> V, ? extends V&gt; remappingFunction)</span></span>;</span><br></pre></td></tr></tbody></table></figure><p>&#x5F88;&#x597D;&#xFF0C;&#x901A;&#x8FC7;&#x8FD9;&#x51E0;&#x4E2A;&#x65B9;&#x6CD5;&#xFF0C;&#x53EF;&#x4EE5;&#x5B8C;&#x7F8E;&#x7684;&#x5427;&#x8001;&#x4EE3;&#x7801;&#x66FF;&#x6362;&#x4E3A;&#x5982;&#x4E0B;&#x4EE3;&#x7801;&#xFF1A;<br></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">return</span> (T) holder.computeIfAbsent(clazzName, key -&gt; createSingleton(clazz, params));</span><br></pre></td></tr></tbody></table></figure><p></p><p>&#x4E00;&#x53E5;&#x8BDD;&#x641E;&#x5B9A;&#xFF0C;&#x7B14;&#x8005;&#x7F8E;&#x6ECB;&#x6ECB;&#x7684;&#x5728;&#x66F4;&#x6539;&#x5B8C;&#x6BD5;&#x540E;&#x8FD0;&#x884C;&#x7A0B;&#x5E8F;&#xFF0C;&#x7136;&#x540E;&#x53D1;&#x73B0;&#x4E86;&#x4E00;&#x4E2A;&#x975E;&#x5E38;&#x5751;&#x7239;&#x7684;&#x73B0;&#x8C61;&#xFF1A;&#x7B14;&#x8005;&#x7684;&#x5E94;&#x7528;&#x963B;&#x585E;&#x5728;&#x67D0;&#x4E2A;&#x70B9;&#x4E0A;&#xFF0C;&#x4E00;&#x81F4;&#x65E0;&#x6CD5;&#x6267;&#x884C;&#x4E0B;&#x53BB;&#x3002;</p><h3 id="&#x8C03;&#x8BD5;"><a href="#&#x8C03;&#x8BD5;" class="headerlink" title="&#x8C03;&#x8BD5;"></a>&#x8C03;&#x8BD5;</h3><p>&#x4E00;&#x5F00;&#x59CB;&#xFF0C;&#x7B14;&#x8005;&#x4EE5;&#x4E3A;&#x662F;&#x81EA;&#x5DF1;&#x7684;&#x5355;&#x4F8B;&#x521B;&#x5EFA;&#x5DE5;&#x5177;&#x9664;&#x4E86;&#x95EE;&#x9898;&#x3002;</p><p>&#x56E0;&#x4E3A;&#xFF0C;&#x8FD9;&#x4E2A;&#x5355;&#x4F8B;&#x5DE5;&#x5177;&#x53C2;&#x7167;&#x4E86;IOC&#x7684;&#x8BBE;&#x8BA1;&#xFF0C;&#x5C06;&#x5BF9;&#x8C61;&#x5B58;&#x50A8;&#x5230;&#x5BB9;&#x5668;&#x5185;&#x3002;&#x5982;&#x679C;&#x6709;&#x8C03;&#x7528;&#x65B9;&#x901A;&#x8FC7;&#x7C7B;&#x4EE5;&#x53CA;&#x6784;&#x9020;&#x5B9E;&#x53C2;&#x8C03;&#x7528;&#xFF0C;&#x5C31;&#x4F1A;&#x5224;&#x65AD;&#x5BB9;&#x5668;&#x5185;&#x662F;&#x5426;&#x5B58;&#x5728;&#xFF0C;&#x5982;&#x679C;&#x5B58;&#x5728;&#x5219;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x5BF9;&#x8C61;&#x3001;&#x4E0D;&#x5B58;&#x5728;&#x5219;&#x901A;&#x8FC7;&#x7C7B;&#x4EE5;&#x53CA;&#x6784;&#x9020;&#x5B9E;&#x53C2;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x5B9E;&#x4F8B;&#x8FD4;&#x56DE;&#x3002;</p><p>&#x7136;&#x540E;&#x5728;&#x5355;&#x6B65;&#x8C03;&#x8BD5;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x53D1;&#x73B0;&#x7ADF;&#x7136;&#x5361;&#x5728;&#x4E86;<code>holder.computeIfAbsent</code>&#x8FD9;&#x4E2A;&#x65B9;&#x6CD5;&#x4E0A;&#xFF0C;&#x90A3;&#x5C31;<code>step into</code>&#x8FDB;&#x53BB;&#x770B;&#x770B;&#x662F;&#x4EC0;&#x4E48;&#x539F;&#x56E0;&#x5BFC;&#x81F4;&#x7684;&#x95EE;&#x9898;&#x3002;</p><p>&#x6700;&#x7EC8;&#x7ECF;&#x8FC7;&#x4E00;&#x7CFB;&#x5217;&#x8C03;&#x8BD5;&#xFF0C;&#x5C06;&#x95EE;&#x9898;&#x5B9A;&#x4F4D;&#x5728;&#x4E86;&#x5982;&#x4E0B;&#x7684;&#x4EE3;&#x7801;&#x7247;&#x6BB5;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">else</span> {</span><br><span class="line">    <span class="keyword">boolean</span> added = <span class="keyword">false</span>;</span><br><span class="line">    <span class="keyword">synchronized</span> (f) {</span><br><span class="line">        <span class="keyword">if</span> (tabAt(tab, i) == f) {</span><br><span class="line">            <span class="keyword">if</span> (fh &gt;= <span class="number">0</span>) {</span><br><span class="line">                binCount = <span class="number">1</span>;</span><br><span class="line">                <span class="keyword">for</span> (Node&lt;K,V&gt; e = f;; ++binCount) {</span><br><span class="line">                    K ek; V ev;</span><br><span class="line">                    <span class="keyword">if</span> (e.hash == h &amp;&amp;</span><br><span class="line">                        ((ek = e.key) == key ||</span><br><span class="line">                         (ek != <span class="keyword">null</span> &amp;&amp; key.equals(ek)))) {</span><br><span class="line">                        val = e.val;</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    }</span><br><span class="line">                    Node&lt;K,V&gt; pred = e;</span><br><span class="line">                    <span class="keyword">if</span> ((e = e.next) == <span class="keyword">null</span>) {</span><br><span class="line">                        <span class="keyword">if</span> ((val = mappingFunction.apply(key)) != <span class="keyword">null</span>) {</span><br><span class="line">                            added = <span class="keyword">true</span>;</span><br><span class="line">                            pred.next = <span class="keyword">new</span> Node&lt;K,V&gt;(h, key, val, <span class="keyword">null</span>);</span><br><span class="line">                        }</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> (f <span class="keyword">instanceof</span> TreeBin) {</span><br><span class="line">                binCount = <span class="number">2</span>;</span><br><span class="line">                TreeBin&lt;K,V&gt; t = (TreeBin&lt;K,V&gt;)f;</span><br><span class="line">                TreeNode&lt;K,V&gt; r, p;</span><br><span class="line">                <span class="keyword">if</span> ((r = t.root) != <span class="keyword">null</span> &amp;&amp;</span><br><span class="line">                    (p = r.findTreeNode(h, key, <span class="keyword">null</span>)) != <span class="keyword">null</span>)</span><br><span class="line">                    val = p.val;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> ((val = mappingFunction.apply(key)) != <span class="keyword">null</span>) {</span><br><span class="line">                    added = <span class="keyword">true</span>;</span><br><span class="line">                    t.putTreeVal(h, key, val);</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">if</span> (binCount != <span class="number">0</span>) {</span><br><span class="line">        <span class="keyword">if</span> (binCount &gt;= TREEIFY_THRESHOLD)</span><br><span class="line">            treeifyBin(tab, i);</span><br><span class="line">        <span class="keyword">if</span> (!added)</span><br><span class="line">            <span class="keyword">return</span> val;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x8FD9;&#x662F;<code>ConcurrentHashMap</code>&#xFF0C;&#x5728;&#x83B7;&#x53D6;<code>key</code>&#x6240;&#x5BF9;&#x5E94;&#x7684;&#x6876;&#xFF08;<code>ConcurrentHashMap</code>&#x5185;&#x90E8;&#x4E00;&#x7EF4;&#x6570;&#x7EC4;&#x6876;+&#x94FE;&#x8868;&#xFF08;&#x7EA2;&#x9ED1;&#x6811;&#xFF09;&#x7ED3;&#x6784;&#xFF09;&#x7684;&#x8FC7;&#x7A0B;&#xFF0C;&#x5982;&#x679C;&#x6876;&#x4E0D;&#x4E3A;&#x7A7A;&#x4E14;&#x4E0D;&#x5728;&#x6269;&#x5BB9;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x5219;&#x4F1A;&#x6267;&#x884C;&#x4E0A;&#x8FF0;&#x8FD9;&#x6BB5;&#x4EE3;&#x7801;&#x3002;</p><p>&#x8FD9;&#x6BB5;&#x4EE3;&#x7801;&#x80AF;&#x5B9A;&#x6CA1;&#x5565;&#x95EE;&#x9898;&#xFF0C;&#x90A3;&#x4E3A;&#x5565;&#x4F1A;&#x5BFC;&#x81F4;&#x4E00;&#x76F4;&#x5728;&#x6B7B;&#x5FAA;&#x73AF;&#xFF0C;&#x800C;&#x6CA1;&#x6CD5;&#x8FDB;&#x5165;&#x67D0;&#x4E2A;&#x5177;&#x4F53;&#x7684;&#x6267;&#x884C;&#x8FC7;&#x7A0B;&#x5462;&#xFF08;fh&#x4E00;&#x76F4;&#x5C0F;&#x4E8E;0&#xFF0C;&#x4E14;&#x4E0D;&#x662F;&#x7EA2;&#x9ED1;&#x6811;&#x8282;&#x70B9;&#xFF09;&#xFF1F;</p><p>&#x4ED4;&#x7EC6;&#x770B;&#x4E86;&#x4E0B;&#x540E;&#xFF0C;&#x7B14;&#x8005;&#x610F;&#x5916;&#x7684;&#x53D1;&#x73B0;&#xFF0C;&#x6240;&#x83B7;&#x53D6;&#x5230;&#x7684;&#x8282;&#x70B9;&#x7ADF;&#x7136;&#x662F;&#x4E00;&#x4E2A;&#x6682;&#x5B58;&#x6001;&#x8282;&#x70B9;&#x3002;&#x4EC0;&#x4E48;&#x53EB;&#x6682;&#x5B58;&#x6001;&#xFF0C;&#x5373;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#x6CA1;&#x6709;&#x771F;&#x6B63;&#x521D;&#x59CB;&#x5316;&#x5B8C;&#x6BD5;&#xFF0C;&#x8282;&#x70B9;&#x7684;&#x72B6;&#x6001;&#x4E3A;<code>RESERVED</code>&#xFF08;-3&#xFF09;&#x3002;</p><p>&#x5B9A;&#x4F4D;&#x5230;&#x539F;&#x56E0;&#xFF1A;&#x5BB9;&#x5668;&#x5185;&#x5B58;&#x5728;&#x6B63;&#x5728;&#x521D;&#x59CB;&#x5316;&#x7684;&#x8282;&#x70B9;&#xFF0C;&#x597D;&#x5DE7;&#x4E0D;&#x5DE7;&#x7684;&#x662F;&#xFF0C;&#x53E6;&#x5916;&#x6709;&#x8C03;&#x7528;&#x65B9;&#x4F7F;&#x7528;<code>computeIfAbsent</code>&#x65B9;&#x6CD5;&#xFF0C;&#x4F20;&#x5165;&#x7684;<code>key</code>hash&#x540E;&#x7684;&#x8282;&#x70B9;&#x6B63;&#x597D;&#x662F;&#x521D;&#x59CB;&#x5316;&#x7684;&#x8282;&#x70B9;&#xFF0C;&#x90A3;&#x5C31;&#x60B2;&#x5267;&#x4E86;&#x3002;&#x540E;&#x9762;&#x7684;&#x65B9;&#x6CD5;&#x9700;&#x8981;&#x7B49;&#x5F85;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#x521D;&#x59CB;&#x5316;&#x5B8C;&#x6BD5;&#x540E;&#x624D;&#x4F1A;&#x6267;&#x884C;&#x6210;&#x529F;&#xFF0C;&#x5426;&#x5219;&#x5C06;&#x6C38;&#x8FDC;&#x5904;&#x4E8E;<code>while</code>&#x6B7B;&#x5FAA;&#x73AF;&#x7684;&#x72B6;&#x6001;&#x3002;&#x800C;&#x7B14;&#x8005;&#x7684;&#x8FD9;&#x79CD;&#x60C5;&#x51B5;&#x5C31;&#x662F;&#x6700;&#x574F;&#x7684;&#x60C5;&#x51B5;&#xFF0C;&#x4E0D;&#x77E5;&#x9053;&#x4EC0;&#x4E48;&#x539F;&#x56E0;&#x5BFC;&#x81F4;&#x524D;&#x8005;&#x521D;&#x59CB;&#x5316;&#x4E00;&#x76F4;&#x5B8C;&#x6210;&#x4E0D;&#x4E86;&#x3002;</p><h3 id="&#x89E3;&#x51B3;"><a href="#&#x89E3;&#x51B3;" class="headerlink" title="&#x89E3;&#x51B3;"></a>&#x89E3;&#x51B3;</h3><p>&#x597D;&#x4E86;&#xFF0C;&#x5B9A;&#x4F4D;&#x5230;&#x4E86;&#x95EE;&#x9898;&#x6240;&#x5728;&#xFF0C;&#x73B0;&#x5728;&#x7684;&#x5173;&#x6CE8;&#x70B9;&#x5728;&#x4E8E;&#xFF0C;&#x4E3A;&#x4EC0;&#x4E48;&#x4F1A;&#x51FA;&#x73B0;&#x524D;&#x8005;&#x4E00;&#x81F4;&#x5904;&#x4E8E;&#x521D;&#x59CB;&#x5316;&#x7684;&#x60C5;&#x51B5;&#xFF1F;</p><p>&#x7B14;&#x8005;&#x5728;&#x83B7;&#x53D6;&#x5355;&#x4F8B;&#x7684;&#x65B9;&#x6CD5;&#x4E0A;&#x505A;&#x4E86;&#x65AD;&#x70B9;&#xFF0C;&#x6BCF;&#x6B21;&#x8C03;&#x7528;&#x540E;&#xFF0C;&#x90FD;&#x67E5;&#x770B;&#x4E0B;&#x5BB9;&#x5668;&#x5185;&#x7684;<code>table</code>&#x5C5E;&#x6027;&#x662F;&#x5426;&#x5B58;&#x5728;&#x521D;&#x59CB;&#x5316;&#x7684;&#x8282;&#x70B9;&#x3002;&#x7136;&#x540E;&#x53D1;&#x73B0;&#x4E86;&#x67D0;&#x4E2A;&#x5BF9;&#x8C61;&#xFF08;A&#xFF09;&#x5728;&#x83B7;&#x53D6;&#x5355;&#x4F8B;&#x540E;&#xFF0C;&#x6CA1;&#x6709;&#x521D;&#x59CB;&#x5316;&#x5B8C;&#x6210;&#xFF0C;&#x800C;&#x53C8;&#x5728;&#x6784;&#x9020;&#x65B9;&#x6CD5;&#x5185;&#x8FDB;&#x884C;&#x4E86;&#x5355;&#x4F8B;&#x7C7B;&#xFF08;B&#xFF09;&#x7684;&#x83B7;&#x53D6;&#x3002;&#x597D;&#x5DE7;&#x4E0D;&#x5DE7;&#xFF0C;A&#x548C;B&#x7684;<code>key</code>&#x5728;<code>hash</code>&#x540E;&#x7684;&#x6876;&#x7D22;&#x5F15;&#x662F;&#x4E00;&#x6837;&#x7684;&#xFF0C;&#x4E5F;&#x5C31;&#x9020;&#x6210;&#x4E86;A&#x5BF9;&#x8C61;&#x5728;&#x7B49;&#x521D;&#x59CB;&#x5316;&#x5B8C;&#x6210;&#xFF0C;&#x521D;&#x59CB;&#x5316;&#x5185;&#x7684;B&#x5BF9;&#x8C61;&#x5728;&#x521D;&#x59CB;&#x5316;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x7531;&#x4E8E;<code>hash</code>&#x51B2;&#x7A81;&#xFF0C;&#x7B49;&#x5F85;&#x8282;&#x70B9;&#x7684;&#x521D;&#x59CB;&#x5316;&#x5B8C;&#x6210;&#xFF0C;&#x5B8C;&#x7F8E;&#x7684;&#x5F62;&#x6210;&#x4E86;&#x6B7B;&#x5FAA;&#x73AF;&#x3002;</p><h3 id="&#x7591;&#x95EE;&#x70B9;"><a href="#&#x7591;&#x95EE;&#x70B9;" class="headerlink" title="&#x7591;&#x95EE;&#x70B9;"></a>&#x7591;&#x95EE;&#x70B9;</h3><p>&#x95EE;&#x9898;&#x4EE5;&#x53CA;&#x539F;&#x56E0;&#x867D;&#x7136;&#x627E;&#x5230;&#x4E86;&#xFF0C;&#x4F46;&#x662F;&#x4E3A;&#x5565;&#x4E4B;&#x524D;&#x7684;&#x5199;&#x6CD5;&#x4F1A;&#x6CA1;&#x6709;&#x95EE;&#x9898;&#x5462;&#xFF1F;&#x4E4B;&#x524D;&#x4E5F;&#x662F;&#x4F7F;&#x7528;&#x4E86;<code>ConcurrentHashMap</code>&#x4F5C;&#x4E3A;&#x5BF9;&#x8C61;&#x5B58;&#x50A8;&#x7684;&#x5BB9;&#x5668;&#xFF0C;&#x6309;&#x7406;&#x4E5F;&#x4F1A;&#x51FA;&#x73B0;&#x8FD9;&#x4E2A;&#x95EE;&#x9898;&#x3002;&#x4ED4;&#x7EC6;&#x770B;&#x4E86;&#x770B;&#x4EE3;&#x7801;&#x540E;&#xFF0C;&#x7B14;&#x8005;&#x604D;&#x7136;&#xFF0C;&#x4E4B;&#x524D;&#x7684;&#x95EE;&#x9898;&#x6240;&#x5728;&#x4E3B;&#x8981;&#x662F;<code>computeIfAbsent</code>&#x5728;&#x8C03;&#x7528;&#x8FC7;&#x7A0B;&#x4E2D;&#x88AB;&#x963B;&#x585E;&#xFF08;&#x8C03;&#x7528;&#x8FC7;&#x7A0B;&#x4E2D;&#x505A;&#x4E86;&#x5BF9;&#x8C61;&#x7684;&#x521B;&#x5EFA;&#xFF09;&#x3002;&#x800C;&#x8001;&#x7684;&#x4EE3;&#x7801;&#x662F;&#xFF1A;&#x5728;&#x521B;&#x5EFA;&#x6210;&#x529F;&#x5355;&#x4F8B;&#x7C7B;&#x4E4B;&#x524D;&#xFF0C;&#x662F;&#x4E0D;&#x5B58;&#x5728;<code>map.put</code>&#x7684;&#x8FC7;&#x7A0B;&#xFF0C;&#x81EA;&#x7136;&#x4E5F;&#x4E0D;&#x4F1A;&#x51FA;&#x73B0;&#x524D;&#x8005;&#x7684;&#x60C5;&#x51B5;&#x3002;</p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h3&gt;&lt;p&gt;今天本来是想要优化下自己的OTA代码，使得效率更高，结果被现实赤裸裸打了脸。&lt;/p&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="collections" scheme="https://xuqiang.me/tags/collections/"/>
    
      <category term="concurrenthashmap" scheme="https://xuqiang.me/tags/concurrenthashmap/"/>
    
  </entry>
  
  <entry>
    <title>HashMap</title>
    <link href="https://xuqiang.me/HashMap.html"/>
    <id>https://xuqiang.me/HashMap.html</id>
    <published>2018-07-22T07:39:52.000Z</published>
    <updated>2018-07-23T14:25:40.000Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x4ECB;&#x7ECD;"><a href="#&#x4ECB;&#x7ECD;" class="headerlink" title="&#x4ECB;&#x7ECD;"></a>&#x4ECB;&#x7ECD;</h3><p>HashMap&#x6E90;&#x4EE3;&#x7801;&#x6CE8;&#x91CA;&#x7FFB;&#x8BD1;&#x4EE5;&#x53CA;&#x4EE3;&#x7801;&#x539F;&#x7406;&#x5206;&#x6790;&#x3002;<br>&#x7248;&#x672C;&#xFF1A;JDK8</p><a id="more"></a><h3 id="&#x6E90;&#x4EE3;&#x7801;&#x7FFB;&#x8BD1;&#x6CE8;&#x91CA;&#x7FFB;&#x8BD1;"><a href="#&#x6E90;&#x4EE3;&#x7801;&#x7FFB;&#x8BD1;&#x6CE8;&#x91CA;&#x7FFB;&#x8BD1;" class="headerlink" title="&#x6E90;&#x4EE3;&#x7801;&#x7FFB;&#x8BD1;&#x6CE8;&#x91CA;&#x7FFB;&#x8BD1;"></a>&#x6E90;&#x4EE3;&#x7801;&#x7FFB;&#x8BD1;&#x6CE8;&#x91CA;&#x7FFB;&#x8BD1;</h3><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br><span class="line">539</span><br><span class="line">540</span><br><span class="line">541</span><br><span class="line">542</span><br><span class="line">543</span><br><span class="line">544</span><br><span class="line">545</span><br><span class="line">546</span><br><span class="line">547</span><br><span class="line">548</span><br><span class="line">549</span><br><span class="line">550</span><br><span class="line">551</span><br><span class="line">552</span><br><span class="line">553</span><br><span class="line">554</span><br><span class="line">555</span><br><span class="line">556</span><br><span class="line">557</span><br><span class="line">558</span><br><span class="line">559</span><br><span class="line">560</span><br><span class="line">561</span><br><span class="line">562</span><br><span class="line">563</span><br><span class="line">564</span><br><span class="line">565</span><br><span class="line">566</span><br><span class="line">567</span><br><span class="line">568</span><br><span class="line">569</span><br><span class="line">570</span><br><span class="line">571</span><br><span class="line">572</span><br><span class="line">573</span><br><span class="line">574</span><br><span class="line">575</span><br><span class="line">576</span><br><span class="line">577</span><br><span class="line">578</span><br><span class="line">579</span><br><span class="line">580</span><br><span class="line">581</span><br><span class="line">582</span><br><span class="line">583</span><br><span class="line">584</span><br><span class="line">585</span><br><span class="line">586</span><br><span class="line">587</span><br><span class="line">588</span><br><span class="line">589</span><br><span class="line">590</span><br><span class="line">591</span><br><span class="line">592</span><br><span class="line">593</span><br><span class="line">594</span><br><span class="line">595</span><br><span class="line">596</span><br><span class="line">597</span><br><span class="line">598</span><br><span class="line">599</span><br><span class="line">600</span><br><span class="line">601</span><br><span class="line">602</span><br><span class="line">603</span><br><span class="line">604</span><br><span class="line">605</span><br><span class="line">606</span><br><span class="line">607</span><br><span class="line">608</span><br><span class="line">609</span><br><span class="line">610</span><br><span class="line">611</span><br><span class="line">612</span><br><span class="line">613</span><br><span class="line">614</span><br><span class="line">615</span><br><span class="line">616</span><br><span class="line">617</span><br><span class="line">618</span><br><span class="line">619</span><br><span class="line">620</span><br><span class="line">621</span><br><span class="line">622</span><br><span class="line">623</span><br><span class="line">624</span><br><span class="line">625</span><br><span class="line">626</span><br><span class="line">627</span><br><span class="line">628</span><br><span class="line">629</span><br><span class="line">630</span><br><span class="line">631</span><br><span class="line">632</span><br><span class="line">633</span><br><span class="line">634</span><br><span class="line">635</span><br><span class="line">636</span><br><span class="line">637</span><br><span class="line">638</span><br><span class="line">639</span><br><span class="line">640</span><br><span class="line">641</span><br><span class="line">642</span><br><span class="line">643</span><br><span class="line">644</span><br><span class="line">645</span><br><span class="line">646</span><br><span class="line">647</span><br><span class="line">648</span><br><span class="line">649</span><br><span class="line">650</span><br><span class="line">651</span><br><span class="line">652</span><br><span class="line">653</span><br><span class="line">654</span><br><span class="line">655</span><br><span class="line">656</span><br><span class="line">657</span><br><span class="line">658</span><br><span class="line">659</span><br><span class="line">660</span><br><span class="line">661</span><br><span class="line">662</span><br><span class="line">663</span><br><span class="line">664</span><br><span class="line">665</span><br><span class="line">666</span><br><span class="line">667</span><br><span class="line">668</span><br><span class="line">669</span><br><span class="line">670</span><br><span class="line">671</span><br><span class="line">672</span><br><span class="line">673</span><br><span class="line">674</span><br><span class="line">675</span><br><span class="line">676</span><br><span class="line">677</span><br><span class="line">678</span><br><span class="line">679</span><br><span class="line">680</span><br><span class="line">681</span><br><span class="line">682</span><br><span class="line">683</span><br><span class="line">684</span><br><span class="line">685</span><br><span class="line">686</span><br><span class="line">687</span><br><span class="line">688</span><br><span class="line">689</span><br><span class="line">690</span><br><span class="line">691</span><br><span class="line">692</span><br><span class="line">693</span><br><span class="line">694</span><br><span class="line">695</span><br><span class="line">696</span><br><span class="line">697</span><br><span class="line">698</span><br><span class="line">699</span><br><span class="line">700</span><br><span class="line">701</span><br><span class="line">702</span><br><span class="line">703</span><br><span class="line">704</span><br><span class="line">705</span><br><span class="line">706</span><br><span class="line">707</span><br><span class="line">708</span><br><span class="line">709</span><br><span class="line">710</span><br><span class="line">711</span><br><span class="line">712</span><br><span class="line">713</span><br><span class="line">714</span><br><span class="line">715</span><br><span class="line">716</span><br><span class="line">717</span><br><span class="line">718</span><br><span class="line">719</span><br><span class="line">720</span><br><span class="line">721</span><br><span class="line">722</span><br><span class="line">723</span><br><span class="line">724</span><br><span class="line">725</span><br><span class="line">726</span><br><span class="line">727</span><br><span class="line">728</span><br><span class="line">729</span><br><span class="line">730</span><br><span class="line">731</span><br><span class="line">732</span><br><span class="line">733</span><br><span class="line">734</span><br><span class="line">735</span><br><span class="line">736</span><br><span class="line">737</span><br><span class="line">738</span><br><span class="line">739</span><br><span class="line">740</span><br><span class="line">741</span><br><span class="line">742</span><br><span class="line">743</span><br><span class="line">744</span><br><span class="line">745</span><br><span class="line">746</span><br><span class="line">747</span><br><span class="line">748</span><br><span class="line">749</span><br><span class="line">750</span><br><span class="line">751</span><br><span class="line">752</span><br><span class="line">753</span><br><span class="line">754</span><br><span class="line">755</span><br><span class="line">756</span><br><span class="line">757</span><br><span class="line">758</span><br><span class="line">759</span><br><span class="line">760</span><br><span class="line">761</span><br><span class="line">762</span><br><span class="line">763</span><br><span class="line">764</span><br><span class="line">765</span><br><span class="line">766</span><br><span class="line">767</span><br><span class="line">768</span><br><span class="line">769</span><br><span class="line">770</span><br><span class="line">771</span><br><span class="line">772</span><br><span class="line">773</span><br><span class="line">774</span><br><span class="line">775</span><br><span class="line">776</span><br><span class="line">777</span><br><span class="line">778</span><br><span class="line">779</span><br><span class="line">780</span><br><span class="line">781</span><br><span class="line">782</span><br><span class="line">783</span><br><span class="line">784</span><br><span class="line">785</span><br><span class="line">786</span><br><span class="line">787</span><br><span class="line">788</span><br><span class="line">789</span><br><span class="line">790</span><br><span class="line">791</span><br><span class="line">792</span><br><span class="line">793</span><br><span class="line">794</span><br><span class="line">795</span><br><span class="line">796</span><br><span class="line">797</span><br><span class="line">798</span><br><span class="line">799</span><br><span class="line">800</span><br><span class="line">801</span><br><span class="line">802</span><br><span class="line">803</span><br><span class="line">804</span><br><span class="line">805</span><br><span class="line">806</span><br><span class="line">807</span><br><span class="line">808</span><br><span class="line">809</span><br><span class="line">810</span><br><span class="line">811</span><br><span class="line">812</span><br><span class="line">813</span><br><span class="line">814</span><br><span class="line">815</span><br><span class="line">816</span><br><span class="line">817</span><br><span class="line">818</span><br><span class="line">819</span><br><span class="line">820</span><br><span class="line">821</span><br><span class="line">822</span><br><span class="line">823</span><br><span class="line">824</span><br><span class="line">825</span><br><span class="line">826</span><br><span class="line">827</span><br><span class="line">828</span><br><span class="line">829</span><br><span class="line">830</span><br><span class="line">831</span><br><span class="line">832</span><br><span class="line">833</span><br><span class="line">834</span><br><span class="line">835</span><br><span class="line">836</span><br><span class="line">837</span><br><span class="line">838</span><br><span class="line">839</span><br><span class="line">840</span><br><span class="line">841</span><br><span class="line">842</span><br><span class="line">843</span><br><span class="line">844</span><br><span class="line">845</span><br><span class="line">846</span><br><span class="line">847</span><br><span class="line">848</span><br><span class="line">849</span><br><span class="line">850</span><br><span class="line">851</span><br><span class="line">852</span><br><span class="line">853</span><br><span class="line">854</span><br><span class="line">855</span><br><span class="line">856</span><br><span class="line">857</span><br><span class="line">858</span><br><span class="line">859</span><br><span class="line">860</span><br><span class="line">861</span><br><span class="line">862</span><br><span class="line">863</span><br><span class="line">864</span><br><span class="line">865</span><br><span class="line">866</span><br><span class="line">867</span><br><span class="line">868</span><br><span class="line">869</span><br><span class="line">870</span><br><span class="line">871</span><br><span class="line">872</span><br><span class="line">873</span><br><span class="line">874</span><br><span class="line">875</span><br><span class="line">876</span><br><span class="line">877</span><br><span class="line">878</span><br><span class="line">879</span><br><span class="line">880</span><br><span class="line">881</span><br><span class="line">882</span><br><span class="line">883</span><br><span class="line">884</span><br><span class="line">885</span><br><span class="line">886</span><br><span class="line">887</span><br><span class="line">888</span><br><span class="line">889</span><br><span class="line">890</span><br><span class="line">891</span><br><span class="line">892</span><br><span class="line">893</span><br><span class="line">894</span><br><span class="line">895</span><br><span class="line">896</span><br><span class="line">897</span><br><span class="line">898</span><br><span class="line">899</span><br><span class="line">900</span><br><span class="line">901</span><br><span class="line">902</span><br><span class="line">903</span><br><span class="line">904</span><br><span class="line">905</span><br><span class="line">906</span><br><span class="line">907</span><br><span class="line">908</span><br><span class="line">909</span><br><span class="line">910</span><br><span class="line">911</span><br><span class="line">912</span><br><span class="line">913</span><br><span class="line">914</span><br><span class="line">915</span><br><span class="line">916</span><br><span class="line">917</span><br><span class="line">918</span><br><span class="line">919</span><br><span class="line">920</span><br><span class="line">921</span><br><span class="line">922</span><br><span class="line">923</span><br><span class="line">924</span><br><span class="line">925</span><br><span class="line">926</span><br><span class="line">927</span><br><span class="line">928</span><br><span class="line">929</span><br><span class="line">930</span><br><span class="line">931</span><br><span class="line">932</span><br><span class="line">933</span><br><span class="line">934</span><br><span class="line">935</span><br><span class="line">936</span><br><span class="line">937</span><br><span class="line">938</span><br><span class="line">939</span><br><span class="line">940</span><br><span class="line">941</span><br><span class="line">942</span><br><span class="line">943</span><br><span class="line">944</span><br><span class="line">945</span><br><span class="line">946</span><br><span class="line">947</span><br><span class="line">948</span><br><span class="line">949</span><br><span class="line">950</span><br><span class="line">951</span><br><span class="line">952</span><br><span class="line">953</span><br><span class="line">954</span><br><span class="line">955</span><br><span class="line">956</span><br><span class="line">957</span><br><span class="line">958</span><br><span class="line">959</span><br><span class="line">960</span><br><span class="line">961</span><br><span class="line">962</span><br><span class="line">963</span><br><span class="line">964</span><br><span class="line">965</span><br><span class="line">966</span><br><span class="line">967</span><br><span class="line">968</span><br><span class="line">969</span><br><span class="line">970</span><br><span class="line">971</span><br><span class="line">972</span><br><span class="line">973</span><br><span class="line">974</span><br><span class="line">975</span><br><span class="line">976</span><br><span class="line">977</span><br><span class="line">978</span><br><span class="line">979</span><br><span class="line">980</span><br><span class="line">981</span><br><span class="line">982</span><br><span class="line">983</span><br><span class="line">984</span><br><span class="line">985</span><br><span class="line">986</span><br><span class="line">987</span><br><span class="line">988</span><br><span class="line">989</span><br><span class="line">990</span><br><span class="line">991</span><br><span class="line">992</span><br><span class="line">993</span><br><span class="line">994</span><br><span class="line">995</span><br><span class="line">996</span><br><span class="line">997</span><br><span class="line">998</span><br><span class="line">999</span><br><span class="line">1000</span><br><span class="line">1001</span><br><span class="line">1002</span><br><span class="line">1003</span><br><span class="line">1004</span><br><span class="line">1005</span><br><span class="line">1006</span><br><span class="line">1007</span><br><span class="line">1008</span><br><span class="line">1009</span><br><span class="line">1010</span><br><span class="line">1011</span><br><span class="line">1012</span><br><span class="line">1013</span><br><span class="line">1014</span><br><span class="line">1015</span><br><span class="line">1016</span><br><span class="line">1017</span><br><span class="line">1018</span><br><span class="line">1019</span><br><span class="line">1020</span><br><span class="line">1021</span><br><span class="line">1022</span><br><span class="line">1023</span><br><span class="line">1024</span><br><span class="line">1025</span><br><span class="line">1026</span><br><span class="line">1027</span><br><span class="line">1028</span><br><span class="line">1029</span><br><span class="line">1030</span><br><span class="line">1031</span><br><span class="line">1032</span><br><span class="line">1033</span><br><span class="line">1034</span><br><span class="line">1035</span><br><span class="line">1036</span><br><span class="line">1037</span><br><span class="line">1038</span><br><span class="line">1039</span><br><span class="line">1040</span><br><span class="line">1041</span><br><span class="line">1042</span><br><span class="line">1043</span><br><span class="line">1044</span><br><span class="line">1045</span><br><span class="line">1046</span><br><span class="line">1047</span><br><span class="line">1048</span><br><span class="line">1049</span><br><span class="line">1050</span><br><span class="line">1051</span><br><span class="line">1052</span><br><span class="line">1053</span><br><span class="line">1054</span><br><span class="line">1055</span><br><span class="line">1056</span><br><span class="line">1057</span><br><span class="line">1058</span><br><span class="line">1059</span><br><span class="line">1060</span><br><span class="line">1061</span><br><span class="line">1062</span><br><span class="line">1063</span><br><span class="line">1064</span><br><span class="line">1065</span><br><span class="line">1066</span><br><span class="line">1067</span><br><span class="line">1068</span><br><span class="line">1069</span><br><span class="line">1070</span><br><span class="line">1071</span><br><span class="line">1072</span><br><span class="line">1073</span><br><span class="line">1074</span><br><span class="line">1075</span><br><span class="line">1076</span><br><span class="line">1077</span><br><span class="line">1078</span><br><span class="line">1079</span><br><span class="line">1080</span><br><span class="line">1081</span><br><span class="line">1082</span><br><span class="line">1083</span><br><span class="line">1084</span><br><span class="line">1085</span><br><span class="line">1086</span><br><span class="line">1087</span><br><span class="line">1088</span><br><span class="line">1089</span><br><span class="line">1090</span><br><span class="line">1091</span><br><span class="line">1092</span><br><span class="line">1093</span><br><span class="line">1094</span><br><span class="line">1095</span><br><span class="line">1096</span><br><span class="line">1097</span><br><span class="line">1098</span><br><span class="line">1099</span><br><span class="line">1100</span><br><span class="line">1101</span><br><span class="line">1102</span><br><span class="line">1103</span><br><span class="line">1104</span><br><span class="line">1105</span><br><span class="line">1106</span><br><span class="line">1107</span><br><span class="line">1108</span><br><span class="line">1109</span><br><span class="line">1110</span><br><span class="line">1111</span><br><span class="line">1112</span><br><span class="line">1113</span><br><span class="line">1114</span><br><span class="line">1115</span><br><span class="line">1116</span><br><span class="line">1117</span><br><span class="line">1118</span><br><span class="line">1119</span><br><span class="line">1120</span><br><span class="line">1121</span><br><span class="line">1122</span><br><span class="line">1123</span><br><span class="line">1124</span><br><span class="line">1125</span><br><span class="line">1126</span><br><span class="line">1127</span><br><span class="line">1128</span><br><span class="line">1129</span><br><span class="line">1130</span><br><span class="line">1131</span><br><span class="line">1132</span><br><span class="line">1133</span><br><span class="line">1134</span><br><span class="line">1135</span><br><span class="line">1136</span><br><span class="line">1137</span><br><span class="line">1138</span><br><span class="line">1139</span><br><span class="line">1140</span><br><span class="line">1141</span><br><span class="line">1142</span><br><span class="line">1143</span><br><span class="line">1144</span><br><span class="line">1145</span><br><span class="line">1146</span><br><span class="line">1147</span><br><span class="line">1148</span><br><span class="line">1149</span><br><span class="line">1150</span><br><span class="line">1151</span><br><span class="line">1152</span><br><span class="line">1153</span><br><span class="line">1154</span><br><span class="line">1155</span><br><span class="line">1156</span><br><span class="line">1157</span><br><span class="line">1158</span><br><span class="line">1159</span><br><span class="line">1160</span><br><span class="line">1161</span><br><span class="line">1162</span><br><span class="line">1163</span><br><span class="line">1164</span><br><span class="line">1165</span><br><span class="line">1166</span><br><span class="line">1167</span><br><span class="line">1168</span><br><span class="line">1169</span><br><span class="line">1170</span><br><span class="line">1171</span><br><span class="line">1172</span><br><span class="line">1173</span><br><span class="line">1174</span><br><span class="line">1175</span><br><span class="line">1176</span><br><span class="line">1177</span><br><span class="line">1178</span><br><span class="line">1179</span><br><span class="line">1180</span><br><span class="line">1181</span><br><span class="line">1182</span><br><span class="line">1183</span><br><span class="line">1184</span><br><span class="line">1185</span><br><span class="line">1186</span><br><span class="line">1187</span><br><span class="line">1188</span><br><span class="line">1189</span><br><span class="line">1190</span><br><span class="line">1191</span><br><span class="line">1192</span><br><span class="line">1193</span><br><span class="line">1194</span><br><span class="line">1195</span><br><span class="line">1196</span><br><span class="line">1197</span><br><span class="line">1198</span><br><span class="line">1199</span><br><span class="line">1200</span><br><span class="line">1201</span><br><span class="line">1202</span><br><span class="line">1203</span><br><span class="line">1204</span><br><span class="line">1205</span><br><span class="line">1206</span><br><span class="line">1207</span><br><span class="line">1208</span><br><span class="line">1209</span><br><span class="line">1210</span><br><span class="line">1211</span><br><span class="line">1212</span><br><span class="line">1213</span><br><span class="line">1214</span><br><span class="line">1215</span><br><span class="line">1216</span><br><span class="line">1217</span><br><span class="line">1218</span><br><span class="line">1219</span><br><span class="line">1220</span><br><span class="line">1221</span><br><span class="line">1222</span><br><span class="line">1223</span><br><span class="line">1224</span><br><span class="line">1225</span><br><span class="line">1226</span><br><span class="line">1227</span><br><span class="line">1228</span><br><span class="line">1229</span><br><span class="line">1230</span><br><span class="line">1231</span><br><span class="line">1232</span><br><span class="line">1233</span><br><span class="line">1234</span><br><span class="line">1235</span><br><span class="line">1236</span><br><span class="line">1237</span><br><span class="line">1238</span><br><span class="line">1239</span><br><span class="line">1240</span><br><span class="line">1241</span><br><span class="line">1242</span><br><span class="line">1243</span><br><span class="line">1244</span><br><span class="line">1245</span><br><span class="line">1246</span><br><span class="line">1247</span><br><span class="line">1248</span><br><span class="line">1249</span><br><span class="line">1250</span><br><span class="line">1251</span><br><span class="line">1252</span><br><span class="line">1253</span><br><span class="line">1254</span><br><span class="line">1255</span><br><span class="line">1256</span><br><span class="line">1257</span><br><span class="line">1258</span><br><span class="line">1259</span><br><span class="line">1260</span><br><span class="line">1261</span><br><span class="line">1262</span><br><span class="line">1263</span><br><span class="line">1264</span><br><span class="line">1265</span><br><span class="line">1266</span><br><span class="line">1267</span><br><span class="line">1268</span><br><span class="line">1269</span><br><span class="line">1270</span><br><span class="line">1271</span><br><span class="line">1272</span><br><span class="line">1273</span><br><span class="line">1274</span><br><span class="line">1275</span><br><span class="line">1276</span><br><span class="line">1277</span><br><span class="line">1278</span><br><span class="line">1279</span><br><span class="line">1280</span><br><span class="line">1281</span><br><span class="line">1282</span><br><span class="line">1283</span><br><span class="line">1284</span><br><span class="line">1285</span><br><span class="line">1286</span><br><span class="line">1287</span><br><span class="line">1288</span><br><span class="line">1289</span><br><span class="line">1290</span><br><span class="line">1291</span><br><span class="line">1292</span><br><span class="line">1293</span><br><span class="line">1294</span><br><span class="line">1295</span><br><span class="line">1296</span><br><span class="line">1297</span><br><span class="line">1298</span><br><span class="line">1299</span><br><span class="line">1300</span><br><span class="line">1301</span><br><span class="line">1302</span><br><span class="line">1303</span><br><span class="line">1304</span><br><span class="line">1305</span><br><span class="line">1306</span><br><span class="line">1307</span><br><span class="line">1308</span><br><span class="line">1309</span><br><span class="line">1310</span><br><span class="line">1311</span><br><span class="line">1312</span><br><span class="line">1313</span><br><span class="line">1314</span><br><span class="line">1315</span><br><span class="line">1316</span><br><span class="line">1317</span><br><span class="line">1318</span><br><span class="line">1319</span><br><span class="line">1320</span><br><span class="line">1321</span><br><span class="line">1322</span><br><span class="line">1323</span><br><span class="line">1324</span><br><span class="line">1325</span><br><span class="line">1326</span><br><span class="line">1327</span><br><span class="line">1328</span><br><span class="line">1329</span><br><span class="line">1330</span><br><span class="line">1331</span><br><span class="line">1332</span><br><span class="line">1333</span><br><span class="line">1334</span><br><span class="line">1335</span><br><span class="line">1336</span><br><span class="line">1337</span><br><span class="line">1338</span><br><span class="line">1339</span><br><span class="line">1340</span><br><span class="line">1341</span><br><span class="line">1342</span><br><span class="line">1343</span><br><span class="line">1344</span><br><span class="line">1345</span><br><span class="line">1346</span><br><span class="line">1347</span><br><span class="line">1348</span><br><span class="line">1349</span><br><span class="line">1350</span><br><span class="line">1351</span><br><span class="line">1352</span><br><span class="line">1353</span><br><span class="line">1354</span><br><span class="line">1355</span><br><span class="line">1356</span><br><span class="line">1357</span><br><span class="line">1358</span><br><span class="line">1359</span><br><span class="line">1360</span><br><span class="line">1361</span><br><span class="line">1362</span><br><span class="line">1363</span><br><span class="line">1364</span><br><span class="line">1365</span><br><span class="line">1366</span><br><span class="line">1367</span><br><span class="line">1368</span><br><span class="line">1369</span><br><span class="line">1370</span><br><span class="line">1371</span><br><span class="line">1372</span><br><span class="line">1373</span><br><span class="line">1374</span><br><span class="line">1375</span><br><span class="line">1376</span><br><span class="line">1377</span><br><span class="line">1378</span><br><span class="line">1379</span><br><span class="line">1380</span><br><span class="line">1381</span><br><span class="line">1382</span><br><span class="line">1383</span><br><span class="line">1384</span><br><span class="line">1385</span><br><span class="line">1386</span><br><span class="line">1387</span><br><span class="line">1388</span><br><span class="line">1389</span><br><span class="line">1390</span><br><span class="line">1391</span><br><span class="line">1392</span><br><span class="line">1393</span><br><span class="line">1394</span><br><span class="line">1395</span><br><span class="line">1396</span><br><span class="line">1397</span><br><span class="line">1398</span><br><span class="line">1399</span><br><span class="line">1400</span><br><span class="line">1401</span><br><span class="line">1402</span><br><span class="line">1403</span><br><span class="line">1404</span><br><span class="line">1405</span><br><span class="line">1406</span><br><span class="line">1407</span><br><span class="line">1408</span><br><span class="line">1409</span><br><span class="line">1410</span><br><span class="line">1411</span><br><span class="line">1412</span><br><span class="line">1413</span><br><span class="line">1414</span><br><span class="line">1415</span><br><span class="line">1416</span><br><span class="line">1417</span><br><span class="line">1418</span><br><span class="line">1419</span><br><span class="line">1420</span><br><span class="line">1421</span><br><span class="line">1422</span><br><span class="line">1423</span><br><span class="line">1424</span><br><span class="line">1425</span><br><span class="line">1426</span><br><span class="line">1427</span><br><span class="line">1428</span><br><span class="line">1429</span><br><span class="line">1430</span><br><span class="line">1431</span><br><span class="line">1432</span><br><span class="line">1433</span><br><span class="line">1434</span><br><span class="line">1435</span><br><span class="line">1436</span><br><span class="line">1437</span><br><span class="line">1438</span><br><span class="line">1439</span><br><span class="line">1440</span><br><span class="line">1441</span><br><span class="line">1442</span><br><span class="line">1443</span><br><span class="line">1444</span><br><span class="line">1445</span><br><span class="line">1446</span><br><span class="line">1447</span><br><span class="line">1448</span><br><span class="line">1449</span><br><span class="line">1450</span><br><span class="line">1451</span><br><span class="line">1452</span><br><span class="line">1453</span><br><span class="line">1454</span><br><span class="line">1455</span><br><span class="line">1456</span><br><span class="line">1457</span><br><span class="line">1458</span><br><span class="line">1459</span><br><span class="line">1460</span><br><span class="line">1461</span><br><span class="line">1462</span><br><span class="line">1463</span><br><span class="line">1464</span><br><span class="line">1465</span><br><span class="line">1466</span><br><span class="line">1467</span><br><span class="line">1468</span><br><span class="line">1469</span><br><span class="line">1470</span><br><span class="line">1471</span><br><span class="line">1472</span><br><span class="line">1473</span><br><span class="line">1474</span><br><span class="line">1475</span><br><span class="line">1476</span><br><span class="line">1477</span><br><span class="line">1478</span><br><span class="line">1479</span><br><span class="line">1480</span><br><span class="line">1481</span><br><span class="line">1482</span><br><span class="line">1483</span><br><span class="line">1484</span><br><span class="line">1485</span><br><span class="line">1486</span><br><span class="line">1487</span><br><span class="line">1488</span><br><span class="line">1489</span><br><span class="line">1490</span><br><span class="line">1491</span><br><span class="line">1492</span><br><span class="line">1493</span><br><span class="line">1494</span><br><span class="line">1495</span><br><span class="line">1496</span><br><span class="line">1497</span><br><span class="line">1498</span><br><span class="line">1499</span><br><span class="line">1500</span><br><span class="line">1501</span><br><span class="line">1502</span><br><span class="line">1503</span><br><span class="line">1504</span><br><span class="line">1505</span><br><span class="line">1506</span><br><span class="line">1507</span><br><span class="line">1508</span><br><span class="line">1509</span><br><span class="line">1510</span><br><span class="line">1511</span><br><span class="line">1512</span><br><span class="line">1513</span><br><span class="line">1514</span><br><span class="line">1515</span><br><span class="line">1516</span><br><span class="line">1517</span><br><span class="line">1518</span><br><span class="line">1519</span><br><span class="line">1520</span><br><span class="line">1521</span><br><span class="line">1522</span><br><span class="line">1523</span><br><span class="line">1524</span><br><span class="line">1525</span><br><span class="line">1526</span><br><span class="line">1527</span><br><span class="line">1528</span><br><span class="line">1529</span><br><span class="line">1530</span><br><span class="line">1531</span><br><span class="line">1532</span><br><span class="line">1533</span><br><span class="line">1534</span><br><span class="line">1535</span><br><span class="line">1536</span><br><span class="line">1537</span><br><span class="line">1538</span><br><span class="line">1539</span><br><span class="line">1540</span><br><span class="line">1541</span><br><span class="line">1542</span><br><span class="line">1543</span><br><span class="line">1544</span><br><span class="line">1545</span><br><span class="line">1546</span><br><span class="line">1547</span><br><span class="line">1548</span><br><span class="line">1549</span><br><span class="line">1550</span><br><span class="line">1551</span><br><span class="line">1552</span><br><span class="line">1553</span><br><span class="line">1554</span><br><span class="line">1555</span><br><span class="line">1556</span><br><span class="line">1557</span><br><span class="line">1558</span><br><span class="line">1559</span><br><span class="line">1560</span><br><span class="line">1561</span><br><span class="line">1562</span><br><span class="line">1563</span><br><span class="line">1564</span><br><span class="line">1565</span><br><span class="line">1566</span><br><span class="line">1567</span><br><span class="line">1568</span><br><span class="line">1569</span><br><span class="line">1570</span><br><span class="line">1571</span><br><span class="line">1572</span><br><span class="line">1573</span><br><span class="line">1574</span><br><span class="line">1575</span><br><span class="line">1576</span><br><span class="line">1577</span><br><span class="line">1578</span><br><span class="line">1579</span><br><span class="line">1580</span><br><span class="line">1581</span><br><span class="line">1582</span><br><span class="line">1583</span><br><span class="line">1584</span><br><span class="line">1585</span><br><span class="line">1586</span><br><span class="line">1587</span><br><span class="line">1588</span><br><span class="line">1589</span><br><span class="line">1590</span><br><span class="line">1591</span><br><span class="line">1592</span><br><span class="line">1593</span><br><span class="line">1594</span><br><span class="line">1595</span><br><span class="line">1596</span><br><span class="line">1597</span><br><span class="line">1598</span><br><span class="line">1599</span><br><span class="line">1600</span><br><span class="line">1601</span><br><span class="line">1602</span><br><span class="line">1603</span><br><span class="line">1604</span><br><span class="line">1605</span><br><span class="line">1606</span><br><span class="line">1607</span><br><span class="line">1608</span><br><span class="line">1609</span><br><span class="line">1610</span><br><span class="line">1611</span><br><span class="line">1612</span><br><span class="line">1613</span><br><span class="line">1614</span><br><span class="line">1615</span><br><span class="line">1616</span><br><span class="line">1617</span><br><span class="line">1618</span><br><span class="line">1619</span><br><span class="line">1620</span><br><span class="line">1621</span><br><span class="line">1622</span><br><span class="line">1623</span><br><span class="line">1624</span><br><span class="line">1625</span><br><span class="line">1626</span><br><span class="line">1627</span><br><span class="line">1628</span><br><span class="line">1629</span><br><span class="line">1630</span><br><span class="line">1631</span><br><span class="line">1632</span><br><span class="line">1633</span><br><span class="line">1634</span><br><span class="line">1635</span><br><span class="line">1636</span><br><span class="line">1637</span><br><span class="line">1638</span><br><span class="line">1639</span><br><span class="line">1640</span><br><span class="line">1641</span><br><span class="line">1642</span><br><span class="line">1643</span><br><span class="line">1644</span><br><span class="line">1645</span><br><span class="line">1646</span><br><span class="line">1647</span><br><span class="line">1648</span><br><span class="line">1649</span><br><span class="line">1650</span><br><span class="line">1651</span><br><span class="line">1652</span><br><span class="line">1653</span><br><span class="line">1654</span><br><span class="line">1655</span><br><span class="line">1656</span><br><span class="line">1657</span><br><span class="line">1658</span><br><span class="line">1659</span><br><span class="line">1660</span><br><span class="line">1661</span><br><span class="line">1662</span><br><span class="line">1663</span><br><span class="line">1664</span><br><span class="line">1665</span><br><span class="line">1666</span><br><span class="line">1667</span><br><span class="line">1668</span><br><span class="line">1669</span><br><span class="line">1670</span><br><span class="line">1671</span><br><span class="line">1672</span><br><span class="line">1673</span><br><span class="line">1674</span><br><span class="line">1675</span><br><span class="line">1676</span><br><span class="line">1677</span><br><span class="line">1678</span><br><span class="line">1679</span><br><span class="line">1680</span><br><span class="line">1681</span><br><span class="line">1682</span><br><span class="line">1683</span><br><span class="line">1684</span><br><span class="line">1685</span><br><span class="line">1686</span><br><span class="line">1687</span><br><span class="line">1688</span><br><span class="line">1689</span><br><span class="line">1690</span><br><span class="line">1691</span><br><span class="line">1692</span><br><span class="line">1693</span><br><span class="line">1694</span><br><span class="line">1695</span><br><span class="line">1696</span><br><span class="line">1697</span><br><span class="line">1698</span><br><span class="line">1699</span><br><span class="line">1700</span><br><span class="line">1701</span><br><span class="line">1702</span><br><span class="line">1703</span><br><span class="line">1704</span><br><span class="line">1705</span><br><span class="line">1706</span><br><span class="line">1707</span><br><span class="line">1708</span><br><span class="line">1709</span><br><span class="line">1710</span><br><span class="line">1711</span><br><span class="line">1712</span><br><span class="line">1713</span><br><span class="line">1714</span><br><span class="line">1715</span><br><span class="line">1716</span><br><span class="line">1717</span><br><span class="line">1718</span><br><span class="line">1719</span><br><span class="line">1720</span><br><span class="line">1721</span><br><span class="line">1722</span><br><span class="line">1723</span><br><span class="line">1724</span><br><span class="line">1725</span><br><span class="line">1726</span><br><span class="line">1727</span><br><span class="line">1728</span><br><span class="line">1729</span><br><span class="line">1730</span><br><span class="line">1731</span><br><span class="line">1732</span><br><span class="line">1733</span><br><span class="line">1734</span><br><span class="line">1735</span><br><span class="line">1736</span><br><span class="line">1737</span><br><span class="line">1738</span><br><span class="line">1739</span><br><span class="line">1740</span><br><span class="line">1741</span><br><span class="line">1742</span><br><span class="line">1743</span><br><span class="line">1744</span><br><span class="line">1745</span><br><span class="line">1746</span><br><span class="line">1747</span><br><span class="line">1748</span><br><span class="line">1749</span><br><span class="line">1750</span><br><span class="line">1751</span><br><span class="line">1752</span><br><span class="line">1753</span><br><span class="line">1754</span><br><span class="line">1755</span><br><span class="line">1756</span><br><span class="line">1757</span><br><span class="line">1758</span><br><span class="line">1759</span><br><span class="line">1760</span><br><span class="line">1761</span><br><span class="line">1762</span><br><span class="line">1763</span><br><span class="line">1764</span><br><span class="line">1765</span><br><span class="line">1766</span><br><span class="line">1767</span><br><span class="line">1768</span><br><span class="line">1769</span><br><span class="line">1770</span><br><span class="line">1771</span><br><span class="line">1772</span><br><span class="line">1773</span><br><span class="line">1774</span><br><span class="line">1775</span><br><span class="line">1776</span><br><span class="line">1777</span><br><span class="line">1778</span><br><span class="line">1779</span><br><span class="line">1780</span><br><span class="line">1781</span><br><span class="line">1782</span><br><span class="line">1783</span><br><span class="line">1784</span><br><span class="line">1785</span><br><span class="line">1786</span><br><span class="line">1787</span><br><span class="line">1788</span><br><span class="line">1789</span><br><span class="line">1790</span><br><span class="line">1791</span><br><span class="line">1792</span><br><span class="line">1793</span><br><span class="line">1794</span><br><span class="line">1795</span><br><span class="line">1796</span><br><span class="line">1797</span><br><span class="line">1798</span><br><span class="line">1799</span><br><span class="line">1800</span><br><span class="line">1801</span><br><span class="line">1802</span><br><span class="line">1803</span><br><span class="line">1804</span><br><span class="line">1805</span><br><span class="line">1806</span><br><span class="line">1807</span><br><span class="line">1808</span><br><span class="line">1809</span><br><span class="line">1810</span><br><span class="line">1811</span><br><span class="line">1812</span><br><span class="line">1813</span><br><span class="line">1814</span><br><span class="line">1815</span><br><span class="line">1816</span><br><span class="line">1817</span><br><span class="line">1818</span><br><span class="line">1819</span><br><span class="line">1820</span><br><span class="line">1821</span><br><span class="line">1822</span><br><span class="line">1823</span><br><span class="line">1824</span><br><span class="line">1825</span><br><span class="line">1826</span><br><span class="line">1827</span><br><span class="line">1828</span><br><span class="line">1829</span><br><span class="line">1830</span><br><span class="line">1831</span><br><span class="line">1832</span><br><span class="line">1833</span><br><span class="line">1834</span><br><span class="line">1835</span><br><span class="line">1836</span><br><span class="line">1837</span><br><span class="line">1838</span><br><span class="line">1839</span><br><span class="line">1840</span><br><span class="line">1841</span><br><span class="line">1842</span><br><span class="line">1843</span><br><span class="line">1844</span><br><span class="line">1845</span><br><span class="line">1846</span><br><span class="line">1847</span><br><span class="line">1848</span><br><span class="line">1849</span><br><span class="line">1850</span><br><span class="line">1851</span><br><span class="line">1852</span><br><span class="line">1853</span><br><span class="line">1854</span><br><span class="line">1855</span><br><span class="line">1856</span><br><span class="line">1857</span><br><span class="line">1858</span><br><span class="line">1859</span><br><span class="line">1860</span><br><span class="line">1861</span><br><span class="line">1862</span><br><span class="line">1863</span><br><span class="line">1864</span><br><span class="line">1865</span><br><span class="line">1866</span><br><span class="line">1867</span><br><span class="line">1868</span><br><span class="line">1869</span><br><span class="line">1870</span><br><span class="line">1871</span><br><span class="line">1872</span><br><span class="line">1873</span><br><span class="line">1874</span><br><span class="line">1875</span><br><span class="line">1876</span><br><span class="line">1877</span><br><span class="line">1878</span><br><span class="line">1879</span><br><span class="line">1880</span><br><span class="line">1881</span><br><span class="line">1882</span><br><span class="line">1883</span><br><span class="line">1884</span><br><span class="line">1885</span><br><span class="line">1886</span><br><span class="line">1887</span><br><span class="line">1888</span><br><span class="line">1889</span><br><span class="line">1890</span><br><span class="line">1891</span><br><span class="line">1892</span><br><span class="line">1893</span><br><span class="line">1894</span><br><span class="line">1895</span><br><span class="line">1896</span><br><span class="line">1897</span><br><span class="line">1898</span><br><span class="line">1899</span><br><span class="line">1900</span><br><span class="line">1901</span><br><span class="line">1902</span><br><span class="line">1903</span><br><span class="line">1904</span><br><span class="line">1905</span><br><span class="line">1906</span><br><span class="line">1907</span><br><span class="line">1908</span><br><span class="line">1909</span><br><span class="line">1910</span><br><span class="line">1911</span><br><span class="line">1912</span><br><span class="line">1913</span><br><span class="line">1914</span><br><span class="line">1915</span><br><span class="line">1916</span><br><span class="line">1917</span><br><span class="line">1918</span><br><span class="line">1919</span><br><span class="line">1920</span><br><span class="line">1921</span><br><span class="line">1922</span><br><span class="line">1923</span><br><span class="line">1924</span><br><span class="line">1925</span><br><span class="line">1926</span><br><span class="line">1927</span><br><span class="line">1928</span><br><span class="line">1929</span><br><span class="line">1930</span><br><span class="line">1931</span><br><span class="line">1932</span><br><span class="line">1933</span><br><span class="line">1934</span><br><span class="line">1935</span><br><span class="line">1936</span><br><span class="line">1937</span><br><span class="line">1938</span><br><span class="line">1939</span><br><span class="line">1940</span><br><span class="line">1941</span><br><span class="line">1942</span><br><span class="line">1943</span><br><span class="line">1944</span><br><span class="line">1945</span><br><span class="line">1946</span><br><span class="line">1947</span><br><span class="line">1948</span><br><span class="line">1949</span><br><span class="line">1950</span><br><span class="line">1951</span><br><span class="line">1952</span><br><span class="line">1953</span><br><span class="line">1954</span><br><span class="line">1955</span><br><span class="line">1956</span><br><span class="line">1957</span><br><span class="line">1958</span><br><span class="line">1959</span><br><span class="line">1960</span><br><span class="line">1961</span><br><span class="line">1962</span><br><span class="line">1963</span><br><span class="line">1964</span><br><span class="line">1965</span><br><span class="line">1966</span><br><span class="line">1967</span><br><span class="line">1968</span><br><span class="line">1969</span><br><span class="line">1970</span><br><span class="line">1971</span><br><span class="line">1972</span><br><span class="line">1973</span><br><span class="line">1974</span><br><span class="line">1975</span><br><span class="line">1976</span><br><span class="line">1977</span><br><span class="line">1978</span><br><span class="line">1979</span><br><span class="line">1980</span><br><span class="line">1981</span><br><span class="line">1982</span><br><span class="line">1983</span><br><span class="line">1984</span><br><span class="line">1985</span><br><span class="line">1986</span><br><span class="line">1987</span><br><span class="line">1988</span><br><span class="line">1989</span><br><span class="line">1990</span><br><span class="line">1991</span><br><span class="line">1992</span><br><span class="line">1993</span><br><span class="line">1994</span><br><span class="line">1995</span><br><span class="line">1996</span><br><span class="line">1997</span><br><span class="line">1998</span><br><span class="line">1999</span><br><span class="line">2000</span><br><span class="line">2001</span><br><span class="line">2002</span><br><span class="line">2003</span><br><span class="line">2004</span><br><span class="line">2005</span><br><span class="line">2006</span><br><span class="line">2007</span><br><span class="line">2008</span><br><span class="line">2009</span><br><span class="line">2010</span><br><span class="line">2011</span><br><span class="line">2012</span><br><span class="line">2013</span><br><span class="line">2014</span><br><span class="line">2015</span><br><span class="line">2016</span><br><span class="line">2017</span><br><span class="line">2018</span><br><span class="line">2019</span><br><span class="line">2020</span><br><span class="line">2021</span><br><span class="line">2022</span><br><span class="line">2023</span><br><span class="line">2024</span><br><span class="line">2025</span><br><span class="line">2026</span><br><span class="line">2027</span><br><span class="line">2028</span><br><span class="line">2029</span><br><span class="line">2030</span><br><span class="line">2031</span><br><span class="line">2032</span><br><span class="line">2033</span><br><span class="line">2034</span><br><span class="line">2035</span><br><span class="line">2036</span><br><span class="line">2037</span><br><span class="line">2038</span><br><span class="line">2039</span><br><span class="line">2040</span><br><span class="line">2041</span><br><span class="line">2042</span><br><span class="line">2043</span><br><span class="line">2044</span><br><span class="line">2045</span><br><span class="line">2046</span><br><span class="line">2047</span><br><span class="line">2048</span><br><span class="line">2049</span><br><span class="line">2050</span><br><span class="line">2051</span><br><span class="line">2052</span><br><span class="line">2053</span><br><span class="line">2054</span><br><span class="line">2055</span><br><span class="line">2056</span><br><span class="line">2057</span><br><span class="line">2058</span><br><span class="line">2059</span><br><span class="line">2060</span><br><span class="line">2061</span><br><span class="line">2062</span><br><span class="line">2063</span><br><span class="line">2064</span><br><span class="line">2065</span><br><span class="line">2066</span><br><span class="line">2067</span><br><span class="line">2068</span><br><span class="line">2069</span><br><span class="line">2070</span><br><span class="line">2071</span><br><span class="line">2072</span><br><span class="line">2073</span><br><span class="line">2074</span><br><span class="line">2075</span><br><span class="line">2076</span><br><span class="line">2077</span><br><span class="line">2078</span><br><span class="line">2079</span><br><span class="line">2080</span><br><span class="line">2081</span><br><span class="line">2082</span><br><span class="line">2083</span><br><span class="line">2084</span><br><span class="line">2085</span><br><span class="line">2086</span><br><span class="line">2087</span><br><span class="line">2088</span><br><span class="line">2089</span><br><span class="line">2090</span><br><span class="line">2091</span><br><span class="line">2092</span><br><span class="line">2093</span><br><span class="line">2094</span><br><span class="line">2095</span><br><span class="line">2096</span><br><span class="line">2097</span><br><span class="line">2098</span><br><span class="line">2099</span><br><span class="line">2100</span><br><span class="line">2101</span><br><span class="line">2102</span><br><span class="line">2103</span><br><span class="line">2104</span><br><span class="line">2105</span><br><span class="line">2106</span><br><span class="line">2107</span><br><span class="line">2108</span><br><span class="line">2109</span><br><span class="line">2110</span><br><span class="line">2111</span><br><span class="line">2112</span><br><span class="line">2113</span><br><span class="line">2114</span><br><span class="line">2115</span><br><span class="line">2116</span><br><span class="line">2117</span><br><span class="line">2118</span><br><span class="line">2119</span><br><span class="line">2120</span><br><span class="line">2121</span><br><span class="line">2122</span><br><span class="line">2123</span><br><span class="line">2124</span><br><span class="line">2125</span><br><span class="line">2126</span><br><span class="line">2127</span><br><span class="line">2128</span><br><span class="line">2129</span><br><span class="line">2130</span><br><span class="line">2131</span><br><span class="line">2132</span><br><span class="line">2133</span><br><span class="line">2134</span><br><span class="line">2135</span><br><span class="line">2136</span><br><span class="line">2137</span><br><span class="line">2138</span><br><span class="line">2139</span><br><span class="line">2140</span><br><span class="line">2141</span><br><span class="line">2142</span><br><span class="line">2143</span><br><span class="line">2144</span><br><span class="line">2145</span><br><span class="line">2146</span><br><span class="line">2147</span><br><span class="line">2148</span><br><span class="line">2149</span><br><span class="line">2150</span><br><span class="line">2151</span><br><span class="line">2152</span><br><span class="line">2153</span><br><span class="line">2154</span><br><span class="line">2155</span><br><span class="line">2156</span><br><span class="line">2157</span><br><span class="line">2158</span><br><span class="line">2159</span><br><span class="line">2160</span><br><span class="line">2161</span><br><span class="line">2162</span><br><span class="line">2163</span><br><span class="line">2164</span><br><span class="line">2165</span><br><span class="line">2166</span><br><span class="line">2167</span><br><span class="line">2168</span><br><span class="line">2169</span><br><span class="line">2170</span><br><span class="line">2171</span><br><span class="line">2172</span><br><span class="line">2173</span><br><span class="line">2174</span><br><span class="line">2175</span><br><span class="line">2176</span><br><span class="line">2177</span><br><span class="line">2178</span><br><span class="line">2179</span><br><span class="line">2180</span><br><span class="line">2181</span><br><span class="line">2182</span><br><span class="line">2183</span><br><span class="line">2184</span><br><span class="line">2185</span><br><span class="line">2186</span><br><span class="line">2187</span><br><span class="line">2188</span><br><span class="line">2189</span><br><span class="line">2190</span><br><span class="line">2191</span><br><span class="line">2192</span><br><span class="line">2193</span><br><span class="line">2194</span><br><span class="line">2195</span><br><span class="line">2196</span><br><span class="line">2197</span><br><span class="line">2198</span><br><span class="line">2199</span><br><span class="line">2200</span><br><span class="line">2201</span><br><span class="line">2202</span><br><span class="line">2203</span><br><span class="line">2204</span><br><span class="line">2205</span><br><span class="line">2206</span><br><span class="line">2207</span><br><span class="line">2208</span><br><span class="line">2209</span><br><span class="line">2210</span><br><span class="line">2211</span><br><span class="line">2212</span><br><span class="line">2213</span><br><span class="line">2214</span><br><span class="line">2215</span><br><span class="line">2216</span><br><span class="line">2217</span><br><span class="line">2218</span><br><span class="line">2219</span><br><span class="line">2220</span><br><span class="line">2221</span><br><span class="line">2222</span><br><span class="line">2223</span><br><span class="line">2224</span><br><span class="line">2225</span><br><span class="line">2226</span><br><span class="line">2227</span><br><span class="line">2228</span><br><span class="line">2229</span><br><span class="line">2230</span><br><span class="line">2231</span><br><span class="line">2232</span><br><span class="line">2233</span><br><span class="line">2234</span><br><span class="line">2235</span><br><span class="line">2236</span><br><span class="line">2237</span><br><span class="line">2238</span><br><span class="line">2239</span><br><span class="line">2240</span><br><span class="line">2241</span><br><span class="line">2242</span><br><span class="line">2243</span><br><span class="line">2244</span><br><span class="line">2245</span><br><span class="line">2246</span><br><span class="line">2247</span><br><span class="line">2248</span><br><span class="line">2249</span><br><span class="line">2250</span><br><span class="line">2251</span><br><span class="line">2252</span><br><span class="line">2253</span><br><span class="line">2254</span><br><span class="line">2255</span><br><span class="line">2256</span><br><span class="line">2257</span><br><span class="line">2258</span><br><span class="line">2259</span><br><span class="line">2260</span><br><span class="line">2261</span><br><span class="line">2262</span><br><span class="line">2263</span><br><span class="line">2264</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> java.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.io.InvalidObjectException;</span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.ParameterizedType;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Type;</span><br><span class="line"><span class="keyword">import</span> java.util.function.BiConsumer;</span><br><span class="line"><span class="keyword">import</span> java.util.function.BiFunction;</span><br><span class="line"><span class="keyword">import</span> java.util.function.Consumer;</span><br><span class="line"><span class="keyword">import</span> java.util.function.Function;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Hash table &#x57FA;&#x4E8E; &lt;tt&gt;Map&lt;/tt&gt; &#x63A5;&#x53E3;&#x5B9E;&#x73B0;.</span></span><br><span class="line"><span class="comment"> * &#x8FD9;&#x4E2A;&#x5B9E;&#x73B0;&#x63D0;&#x4F9B;&#x4E86;&#x6240;&#x6709;map&#x7684;&#x53EF;&#x9009;&#x64CD;&#x4F5C;&#xFF0C;&#x5E76;&#x4E14;&#x5141;&#x8BB8; value &#x4E3A; &lt;tt&gt;null&lt;/tt&gt; &#x548C; key &#x4E3A; </span></span><br><span class="line"><span class="comment"> * &lt;tt&gt;null&lt;/tt&gt;&#x3002; ( &lt;tt&gt;HashMap&lt;/tt&gt; &#x7C7B;&#x5927;&#x81F4;&#x4E0E; &lt;tt&gt;Hashtable&lt;/tt&gt; &#x7C7B;&#x4F3C;&#xFF0C;&#x9664;&#x4E86;</span></span><br><span class="line"><span class="comment"> * &#x5B83;&#x662F;&#x975E;&#x7EBF;&#x7A0B;&#x5B89;&#x5168;&#x7684;&#x5E76;&#x4E14;&#x5141;&#x8BB8;null)&#x3002;&#x8BE5;&#x7C7B;&#x5E76;&#x4E0D;&#x4FDD;&#x8BC1;&#x987A;&#x5E8F;map&#x7684;&#x987A;&#x5E8F;&#x4E00;&#x81F4;&#xFF1B;&#x7279;&#x522B;&#x662F;&#xFF0C;&#x5B83;&#x4E0D;&#x4FDD;&#x8BC1;&#x987A;&#x5E8F;</span></span><br><span class="line"><span class="comment"> * &#x4F1A;&#x968F;&#x7740;&#x65F6;&#x95F4;&#x7684;&#x53D8;&#x5316;&#x4FDD;&#x6301;&#x4E00;&#x81F4;&#x3002;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;&#x5047;&#x8BBE;&#x6563;&#x5217;&#x51FD;&#x6570;&#x5728;&#x6876;&#x4E4B;&#x95F4;&#x80FD;&#x591F;&#x505A;&#x5230;&#x7406;&#x60F3;&#x5316;&#x7684;&#x5206;&#x5E03;&#xFF0C;&#x90A3;&#x4E48;&#x6B64;&#x5B9E;&#x73B0;&#x80FD;&#x591F;&#x4E3A;&#x57FA;&#x672C;&#x64CD;&#x4F5C;&#x63D0;&#x4F9B;&#x5E38;&#x6570;&#x7EA7;&#x7684;&#x6027;&#x80FD; (&#x6BD4;</span></span><br><span class="line"><span class="comment"> * &#x5982; &lt;tt&gt;get&lt;/tt&gt; &#x548C; &lt;tt&gt;put&lt;/tt&gt; &#x65B9;&#x6CD5;)&#x3002; &#x5BF9;&#x96C6;&#x5408;&#x89C6;&#x56FE;&#x8FED;&#x4EE3;&#x6240;&#x8017;&#x8D39;&#x7684;&#x65F6;&#x95F4;&#x4E0E; </span></span><br><span class="line"><span class="comment"> * &lt;tt&gt;HashMap&lt;/tt&gt; &#x5B9E;&#x4F8B;&#x7684;&quot;capacity&quot;&#x5C5E;&#x6027;&#xFF08;&#x6876;&#x6570;&#x91CF;&#xFF09;&#x52A0;&#x4E0A;&#x5B83;&#x7684;&#x5927;&#x5C0F;&#xFF08;&#x952E;&#x503C;&#x5BF9;&#x6570;&#x91CF;&#xFF09;&#x6210;&#x6B63;&#x6BD4;&#x5173;&#x7CFB;&#x3002;</span></span><br><span class="line"><span class="comment"> * &#x56E0;&#x6B64;&#xFF0C;&#x5BF9;&#x4E8E;&#x8FED;&#x4EE3;&#x6027;&#x80FD;&#x6765;&#x8BF4;&#xFF0C;&#x4E0D;&#x8981;&#x5C06;&#x521D;&#x59CB;&#x5BB9;&#x91CF;[capacity]&#x8BBE;&#x7F6E;&#x7684;&#x592A;&#x9AD8;&#xFF08;&#x6216;&#x8005;&#x5C06;&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;[loadFactor]</span></span><br><span class="line"><span class="comment"> * &#x8BBE;&#x7F6E;&#x7684;&#x592A;&#x4F4E;&#xFF09;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;&#x5BF9;&#x4E8E;&#x4E00;&#x4E2A; &lt;tt&gt;HashMap&lt;/tt&gt; &#x5B9E;&#x4F8B;&#x6709;&#x4E24;&#x4E2A;&#x5C5E;&#x6027;&#x5F71;&#x54CD;&#x5B83;&#x7684;&#x6027;&#x80FD;&#xFF1A;&lt;i&gt;initial capacity&lt;/i&gt; </span></span><br><span class="line"><span class="comment"> * &#x548C; &lt;i&gt;load factor&lt;/i&gt;&#x3002; &lt;i&gt;capacity&lt;/i&gt; &#x662F;hash&#x8868;&#x7684;&#x6876;&#x6570;&#x91CF;&#xFF0C;&#x521D;&#x59CB;&#x7684;&#x5BB9;&#x91CF;&#x53EA;&#x662F;hash&#x8868;&#x88AB;</span></span><br><span class="line"><span class="comment"> * &#x521B;&#x5EFA;&#x65F6;&#x7684;&#x5BB9;&#x91CF;&#x3002;&lt;i&gt;load factor&lt;/i&gt; &#x7528;&#x4E8E;&#x5728;hash&#x8868;&#x589E;&#x52A0;&#x5BB9;&#x91CF;&#x4E4B;&#x524D;&#x8861;&#x91CF;hash&#x8868;&#x7684;&#x8D1F;&#x8F7D;&#x60C5;&#x51B5;&#x662F;&#x5426;</span></span><br><span class="line"><span class="comment"> * &#x9700;&#x8981;&#x6269;&#x5BB9;&#x3002;&#x5F53;hash&#x8868;&#x7684;&#x952E;&#x503C;&#x5BF9;&#x6570;&#x91CF;&#x8D85;&#x8FC7;&#x5F53;&#x524D;&#x5BB9;&#x91CF;&#x548C;&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;&#x7684;&#x4E58;&#x79EF;&#x7684;&#x65F6;&#x5019;&#xFF0C;hash&#x8868;&#x5C06;&#x4F1A;&#x88AB;</span></span><br><span class="line"><span class="comment"> * &lt;i&gt;rehashed&lt;/i&gt; (&#x4E5F;&#x5C31;&#x662F;&#x8BF4;&#xFF0C;&#x5185;&#x90E8;&#x7684;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x5C06;&#x4F1A;&#x88AB;&#x91CD;&#x65B0;&#x6784;&#x5EFA;)&#x4ECE;&#x800C;&#x8FBE;&#x5230;&#x8FD1;&#x4F3C;&#x539F;&#x6709;&#x4E24;&#x500D;&#x7684;&#x6876;&#x6570;&#x91CF;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;&#x4F5C;&#x4E3A;&#x901A;&#x7528;&#x89C4;&#x5219;&#x6765;&#x8BF4;&#xFF0C;&#x9ED8;&#x8BA4;&#x7684;&#x8D1F;&#x8F7D;&#x56E0;&#x5B50; (.75) &#x5728;&#x65F6;&#x95F4;&#x548C;&#x7A7A;&#x95F4;&#x6210;&#x672C;&#x4E0A;&#x8FBE;&#x5230;&#x4E86;&#x826F;&#x597D;&#x7684;&#x5E73;&#x8861;&#x3002;&#x8F83;&#x9AD8;&#x7684;&#x503C;&#x4F1A;</span></span><br><span class="line"><span class="comment"> * &#x51CF;&#x5C11;&#x7A7A;&#x95F4;&#x6210;&#x672C;&#x7684;&#x540C;&#x65F6;&#x5374;&#x589E;&#x52A0;&#x4E86;&#x67E5;&#x627E;&#x7684;&#x6210;&#x672C;&#xFF08;&#x53CD;&#x6620;&#x5728;&#x5927;&#x591A;&#x6570; &lt;tt&gt;HashMap&lt;/tt&gt; &#x7C7B;&#x7684;&#x65B9;&#x6CD5;&#x4E0A;&#xFF0C;&#x5305;&#x62EC;</span></span><br><span class="line"><span class="comment"> * &lt;tt&gt;get&lt;/tt&gt; &#x548C; &lt;tt&gt;put&lt;/tt&gt;&#xFF09;&#x3002;&#x5728;&#x8BBE;&#x7F6E;&#x5176;&#x521D;&#x59CB;&#x5BB9;&#x91CF;&#x65F6;&#xFF0C;&#x5E94;&#x8003;&#x8651;&#x6620;&#x5C04;&#x4E2D;&#x7684;&#x952E;&#x503C;&#x5BF9;&#x6570;&#x53CA;&#x5176;&#x8D1F;&#x8F7D;&#x56E0;</span></span><br><span class="line"><span class="comment"> * &#x5B50;&#xFF0C;&#x4EE5;&#x4FBF;&#x5C3D;&#x91CF;&#x51CF;&#x5C11;&#x91CD;&#x65B0;&#x6563;&#x5217;&#x7684;&#x64CD;&#x4F5C;&#x3002; &#x5982;&#x679C;&#x521D;&#x59CB;&#x5BB9;&#x91CF;&#x5927;&#x4E8E;&#x6700;&#x5927;&#x952E;&#x503C;&#x5BF9;&#x6570;&#x9664;&#x4EE5;&#x52A0;&#x8F7D;&#x56E0;&#x5B50;&#xFF0C;&#x5219;&#x4E0D;&#x4F1A;&#x6267;&#x884C;&#x91CD;&#x65B0;</span></span><br><span class="line"><span class="comment"> * &#x6563;&#x5217;&#x3002;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;&#x5F53;&#x5927;&#x91CF;&#x952E;&#x503C;&#x5BF9;&#x88AB;&#x5B58;&#x50A8;&#x5230;&#x4E00;&#x4E2A; &lt;tt&gt;HashMap&lt;/tt&gt; &#x5B9E;&#x4F8B;&#x5185;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x90A3;&#x4E48;&#x4F7F;&#x7528;&#x4E00;&#x4E2A;&#x8DB3;&#x591F;&#x5927;&#x7684;&#x5BB9;&#x5668;&#x6765;</span></span><br><span class="line"><span class="comment"> * &#x5B58;&#x50A8;&#x8FD9;&#x4E9B;&#x952E;&#x503C;&#x5BF9;&#x5C06;&#x6BD4;&#x8BA9;&#x5B83;&#x4EEC;&#x81EA;&#x884C;&#x5728;&#x9700;&#x8981;&#x7684;&#x65F6;&#x5019;&#x91CD;&#x65B0;&#x6563;&#x5217;&#x4EE5;&#x589E;&#x52A0;&#x8868;&#x7A7A;&#x95F4;&#x6765;&#x7684;&#x66F4;&#x6709;&#x6548;&#x7387;&#x3002;&#x9700;&#x8981;&#x6CE8;&#x610F;&#x7684;&#x662F;&#xFF0C;</span></span><br><span class="line"><span class="comment"> * &#x4F7F;&#x7528;&#x5F88;&#x591A;&#x5177;&#x6709;&#x76F8;&#x540C;{<span class="doctag">@code</span> hashCode()}&#x7684;key&#x662F;&#x964D;&#x4F4E;hash&#x8868;&#x6027;&#x80FD;&#x7684;&#x786E;&#x5B9A;&#x6027;&#x56E0;&#x7D20;&#x3002;&#x4E3A;&#x4E86;&#x6539;&#x5584;&#x8FD9;&#x4E2A;&#x56E0;&#x7D20;</span></span><br><span class="line"><span class="comment"> * &#xFF0C;&#x5F53;key&#x662F;&#x53EF;&#x88AB;&#x6BD4;&#x8F83;&#x7684;&#x65F6;&#x5019;&#xFF08;{<span class="doctag">@link</span> Comparable}&#xFF09;&#xFF0C;&#x8FD9;&#x4E2A;&#x7C7B;&#x53EF;&#x4EE5;&#x901A;&#x8FC7;&#x4F7F;&#x7528;key&#x4E4B;&#x95F4;&#x7684;&#x6BD4;&#x8F83;&#x987A;&#x5E8F;&#x6765;&#x5E2E;</span></span><br><span class="line"><span class="comment"> * &#x52A9;&#x6253;&#x7834;&#x8FD9;&#x4E00;&#x675F;&#x7F1A;&#x3002;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;P&gt;&lt;strong&gt;&#x7279;&#x522B;&#x9700;&#x8981;&#x6CE8;&#x610F;&#x6B64;&#x5B9E;&#x73B0;&#x662F;&#x7EBF;&#x7A0B;&#x4E0D;&#x5B89;&#x5168;&#x7684;&#x3002;&lt;/string&gt;</span></span><br><span class="line"><span class="comment"> * &#x5982;&#x679C;&#x591A;&#x7EBF;&#x7A0B;&#x5E76;&#x53D1;&#x8BBF;&#x95EE;&#x4E00;&#x4E2A;hash map&#x4E14;&#x81F3;&#x5C11;&#x6709;&#x4E00;&#x4E2A;&#x7EBF;&#x7A0B;&#x4FEE;&#x6539;&#x4E86;map&#x7684;&#x7ED3;&#x679C;&#xFF0C;&#x90A3;&#x4E48;&#x5B83; &lt;i&gt;&#x5FC5;&#x987B;&lt;/i&gt; &#x505A;&#x5230;</span></span><br><span class="line"><span class="comment"> * &#x5916;&#x90E8;&#x540C;&#x6B65;&#x3002;&#xFF08;&#x589E;&#x52A0;&#x6216;&#x8005;&#x5220;&#x9664;&#x4E00;&#x4E2A;&#x6216;&#x591A;&#x4E2A;&#x952E;&#x503C;&#x5BF9;&#x7684;&#x64CD;&#x4F5C;&#x662F;&#x7ED3;&#x6784;&#x5316;&#x53D8;&#x66F4;&#x64CD;&#x4F5C;&#xFF1B;&#x4EC5;&#x4EC5;&#x66F4;&#x6539;&#x5DF2;&#x7ECF;&#x5B58;&#x5728;&#x7684;&#x952E;&#x503C;&#x5BF9;&#x7684;</span></span><br><span class="line"><span class="comment"> * &#x503C;&#x4E0D;&#x662F;&#x7ED3;&#x6784;&#x5316;&#x53D8;&#x66F4;&#x64CD;&#x4F5C;&#x3002;&#xFF09; &#x8FD9;&#x901A;&#x5E38;&#x901A;&#x8FC7;&#x540C;&#x6B65;&#x5316;&#x5C01;&#x88C5;map&#x7684;&#x5BF9;&#x8C61;&#x6765;&#x5B9E;&#x73B0;&#x3002;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &#x5982;&#x679C;&#x6CA1;&#x6709;&#x8FD9;&#x4E48;&#x4E2A;&#x5BF9;&#x8C61;&#x5B58;&#x5728;&#xFF0C;&#x90A3;&#x4E48;&#x5E94;&#x8BE5;&#x901A;&#x8FC7;&#x4F7F;&#x7528;{<span class="doctag">@link</span> Collections#synchronizedMap Collections.synchronizedMap}</span></span><br><span class="line"><span class="comment"> * &#x65B9;&#x6CD5;&#x6765;&#x201C;&#x5305;&#x88F9;&#x201D; map &#x5BF9;&#x8C61;&#x3002; &#x8FD9;&#x4E2A;&#x5BF9;&#x53F7;&#x5728;&#x521B;&#x5EFA;&#x65F6;&#x5B8C;&#x6210;&#xFF0C;&#x4EE5;&#x6B64;&#x9632;&#x6B62;&#x610F;&#x5916;&#x7684;&#x5BF9;map&#x505A;&#x975E;&#x540C;&#x6B65;&#x5316;&#x8BBF;&#x95EE;&#xFF1A;&lt;pre&gt;</span></span><br><span class="line"><span class="comment"> *   Map m = Collections.synchronizedMap(new HashMap(...));&lt;/pre&gt;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;&#x6240;&#x6709;&#x5BF9;&#x8C61;&#x7684;&#x201C;&#x96C6;&#x5408;&#x89C6;&#x56FE;&#x65B9;&#x6CD5;&#x201D;&#x8FD4;&#x56DE;&#x7684;&#x8FED;&#x4EE3;&#x5668;&#x90FD;&#x662F; &lt;i&gt;fail-fast&lt;/i&gt;&#x673A;&#x5236;&#xFF1A;&#x5982;&#x679C;&#x5728;&#x521B;&#x5EFA;&#x8FED;&#x4EE3;&#x5668;&#x540E;&#xFF0C;</span></span><br><span class="line"><span class="comment"> * map&#x5728;&#x4EFB;&#x610F;&#x65F6;&#x95F4;&#x70B9;&#x88AB;&#x7ED3;&#x6784;&#x5316;&#x66F4;&#x6539;&#xFF08;&#x9664;&#x4E86;&#x901A;&#x8FC7;&#x8FED;&#x4EE3;&#x5668;&#x81EA;&#x5DF1;&#x7684; &lt;tt&gt;remove&lt;/tt&gt; &#x65B9;&#x6CD5;&#x9020;&#x6210;&#x7684;&#x7ED3;&#x6784;&#x53D8;&#x66F4;&#x4E4B;</span></span><br><span class="line"><span class="comment"> * &#x5916;&#xFF09;&#xFF0C;&#x8FED;&#x4EE3;&#x5668;&#x5C06;&#x4F1A;&#x629B;&#x51FA;&#x4E00;&#x4E2A;{<span class="doctag">@link</span> ConcurrentModificationException}&#x5F02;&#x5E38;&#x3002;&#x6240;&#x4EE5;&#xFF0C;&#x9762;&#x5BF9;&#x5E76;</span></span><br><span class="line"><span class="comment"> * &#x53D1;&#x4FEE;&#x6539;&#xFF0C;&#x8FED;&#x4EE3;&#x5668;&#x5FEB;&#x901F;&#x5229;&#x843D;&#x7684;&#x5931;&#x8D25;&#x800C;&#x4E0D;&#x662F;&#x5728;&#x672A;&#x6765;&#x7684;&#x4E0D;&#x786E;&#x5B9A;&#x65F6;&#x95F4;&#x5192;&#x4EFB;&#x610F;&#x3001;&#x4E0D;&#x786E;&#x5B9A;&#x6027;&#x7684;&#x98CE;&#x9669;&#x3002;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;&#x9700;&#x8981;&#x6CE8;&#x610F;&#x8FED;&#x4EE3;&#x5668;&#x7684;&#x5FEB;&#x901F;&#x5931;&#x8D25;&#x673A;&#x5236;&#x4ECD;&#x65E7;&#x4E0D;&#x80FD;&#x4FDD;&#x8BC1;&#x5B83;&#x539F;&#x6837;&#x5982;&#x6B64;&#xFF0C;&#x4E00;&#x822C;&#x6765;&#x8BF4;&#xFF0C;&#x65E0;&#x6CD5;&#x5728;&#x5E76;&#x53D1;&#x975E;&#x540C;&#x6B65;&#x4FEE;&#x6539;&#x7684;&#x60C5;</span></span><br><span class="line"><span class="comment"> * &#x51B5;&#x4E0B;&#x505A;&#x786C;&#x6027;&#x4FDD;&#x8BC1;&#x3002;&#x5FEB;&#x901F;&#x5931;&#x8D25;&#x7684;&#x8FED;&#x4EE3;&#x5668;&#x629B;&#x51FA; &lt;tt&gt;ConcurrentModificationException&lt;/tt&gt; &#x57FA;&#x4E8E;</span></span><br><span class="line"><span class="comment"> * &#x5C3D;&#x529B;&#x800C;&#x4E3A;&#x539F;&#x5219;&#x3002;&#x56E0;&#x6B64;&#xFF0C;&#x4E3A;&#x4E86;&#x4FDD;&#x8BC1;&#x5B83;&#x7684;&#x6B63;&#x786E;&#x6027;&#x800C;&#x4F9D;&#x8D56;&#x4E8E;&#x8FD9;&#x4E2A;&#x5F02;&#x5E38;&#x53BB;&#x5199;&#x7A0B;&#x5E8F;&#x7684;&#x884C;&#x4E3A;&#x662F;&#x9519;&#x8BEF;&#x7684;&#xFF1A;&lt;i&gt;&#x8FED;&#x4EE3;&#x5668;&#x5FEB;</span></span><br><span class="line"><span class="comment"> * &#x901F;&#x5931;&#x8D25;&#x673A;&#x5236;&#x5E94;&#x8BE5;&#x53EA;&#x88AB;&#x7528;&#x6765;&#x68C0;&#x6D4B;bug&#x3002;&lt;/i&gt;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;&#x8FD9;&#x4E2A;&#x7C7B;&#x662F;</span></span><br><span class="line"><span class="comment"> * &lt;a href=&quot;{<span class="doctag">@docRoot</span>}/../technotes/guides/collections/index.html&quot;&gt;</span></span><br><span class="line"><span class="comment"> * Java&#x96C6;&#x6210;&#x6846;&#x67B6;&#x7684;&#x6210;&#x5458;&lt;/a&gt;.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &lt;K&gt; map&#x7EF4;&#x62A4;&#x7684;&#x952E;&#x7C7B;&#x578B;</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &lt;V&gt; &#x6620;&#x5C04;&#x503C;&#x7684;&#x7C7B;&#x578B;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>  Doug Lea</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>  Josh Bloch</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>  Arthur van Hoff</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>  Neal Gafter</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span>     Object#hashCode()</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span>     Collection</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span>     Map</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span>     TreeMap</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span>     Hashtable</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@since</span>   1.2</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HashMap</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt; <span class="keyword">extends</span> <span class="title">AbstractMap</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;</span></span><br><span class="line"><span class="class">    <span class="keyword">implements</span> <span class="title">Map</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;, <span class="title">Cloneable</span>, <span class="title">Serializable</span> </span>{</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> serialVersionUID = <span class="number">362498820763181265L</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * &#x5B9E;&#x73B0;&#x7B14;&#x8BB0;&#x3002;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * &#x8FD9;&#x4E2A;map&#x5B9E;&#x73B0;&#x901A;&#x5E38;&#x88AB;&#x5F53;&#x505A;&#x4E00;&#x4E2A;&#x5206;&#x6876;&#xFF08;&#x5206;&#x533A;&#xFF09;&#x7684;hash&#x8868;&#xFF0C;&#x4F46;&#x662F;&#x5F53;&#x6876;&#x5185;&#x8282;&#x70B9;&#x7684;&#x6570;&#x91CF;&#x8FC7;&#x4E8E;&#x5E9E;&#x5927;&#x7684;</span></span><br><span class="line"><span class="comment">     * &#x65F6;&#x5019;&#xFF0C;&#x5B83;&#x4EEC;&#x5C06;&#x4F1A;&#x8F6C;&#x5316;&#x4E3A;&#x6811;&#x6876;&#xFF0C;&#x6BCF;&#x4E2A;&#x8282;&#x70B9;&#x7ED3;&#x6784;&#x90FD;&#x4E0E;&#x5728;java.util.TreeMap&#x7684;&#x7C7B;&#x4F3C;&#x3002;&#x5927;&#x591A;</span></span><br><span class="line"><span class="comment">     * &#x6570;&#x65B9;&#x6CD5;&#x5C1D;&#x8BD5;&#x4F7F;&#x7528;&#x666E;&#x901A;&#x7684;&#x8282;&#x70B9;&#xFF0C;&#x4F46;&#x662F;&#x4F1A;&#x5728;&#x9002;&#x5F53;&#x7684;&#x65F6;&#x5019;&#x4F7F;&#x7528;&#x6811;&#x8282;&#x70B9;&#x65B9;&#x6CD5;&#xFF08;&#x53EA;&#x8981;&#x7B80;&#x5355;&#x7684;&#x901A;&#x8FC7;&#x68C0;&#x6D4B;</span></span><br><span class="line"><span class="comment">     * &#x8282;&#x70B9;&#x7684;&#x5B9E;&#x4F8B;&#x5373;&#x53EF;&#xFF09;&#x3002;&#x6811;&#x6876;&#x7684;&#x8282;&#x70B9;&#x53EF;&#x4EE5;&#x50CF;&#x5176;&#x4ED6;&#x666E;&#x901A;&#x8282;&#x70B9;&#x4E00;&#x6837;&#x904D;&#x5386;&#xFF0C;&#x4F46;&#x662F;&#x989D;&#x5916;&#x652F;&#x6301;&#x5728;&#x8282;&#x70B9;&#x6570;&#x91CF;</span></span><br><span class="line"><span class="comment">     * &#x8FC7;&#x591A;&#x7684;&#x65F6;&#x5019;&#x8FDB;&#x884C;&#x5FEB;&#x901F;&#x67E5;&#x8BE2;&#x3002;&#x7136;&#x540E;&#xFF0C;&#x5728;&#x7EDD;&#x5927;&#x591A;&#x6570;&#x5E38;&#x89C4;&#x4F7F;&#x7528;&#x7684;&#x6876;&#x90FD;&#x4E0D;&#x4F1A;&#x51FA;&#x73B0;&#x8282;&#x70B9;&#x6570;&#x91CF;&#x8FC7;&#x591A;&#x7684;&#x60C5;</span></span><br><span class="line"><span class="comment">     * &#x51B5;&#xFF0C;&#x6240;&#x4EE5;&#x5728;hash&#x8868;&#x65B9;&#x6CD5;&#x5185;&#x5C06;&#x4F1A;&#x5EF6;&#x8FDF;&#x68C0;&#x67E5;&#x6811;&#x8282;&#x70B9;&#x662F;&#x5426;&#x5B58;&#x5728;&#x3002;</span></span><br><span class="line"><span class="comment">     * </span></span><br><span class="line"><span class="comment">     * &#x6811;&#x6876;&#xFF08;&#x4E3E;&#x4E2A;&#x4F8B;&#x5B50;&#xFF0C;&#x6876;&#x7684;&#x5143;&#x7D20;&#x8282;&#x70B9;&#x90FD;&#x662F;&#x6811;&#x8282;&#x70B9;&#xFF09;&#x4E3B;&#x8981;&#x6839;&#x636E;hashCode&#x6392;&#x5E8F;&#xFF0C;&#x4F46;&#x662F;&#x5728;&#x67D0;&#x79CD;&#x60C5;&#x51B5;</span></span><br><span class="line"><span class="comment">     * &#x4E0B;&#xFF0C;&#x5982;&#x679C;&#x4E24;&#x4E2A;&#x5143;&#x7D20;&#x90FD;&#x5177;&#x6709;&#x76F8;&#x540C;&#x7684;&quot;class C implements Comparable&lt;C&gt;&quot;&#xFF0C;&#x90A3;&#x4E48;&#x4F1A;</span></span><br><span class="line"><span class="comment">     * &#x4F7F;&#x7528;&#x5B83;&#x4EEC;&#x7684;compareTo&#x65B9;&#x6CD5;&#x505A;&#x6392;&#x5E8F;&#x3002;&#xFF08;&#x6211;&#x4EEC;&#x4FDD;&#x5B88;&#x5730;&#x901A;&#x8FC7;&#x53CD;&#x5C04;&#x6765;&#x68C0;&#x67E5;&#x53CD;&#x5411; &#x2014;&#x2014; &#x53C2;&#x9605; </span></span><br><span class="line"><span class="comment">     * comparableClassFor &#x65B9;&#x6CD5;&#xFF09;&#x3002;&#x5F53;key&#x5177;&#x6709;&#x4E0D;&#x540C;&#x7684;hash&#x503C;&#x6216;&#x8005;&#x662F;&#x6709;&#x5E8F;&#x7684;&#xFF0C;&#x589E;&#x52A0;&#x6811;&#x6876;&#x7684;</span></span><br><span class="line"><span class="comment">     * &#x590D;&#x6742;&#x6027;&#x5BF9;&#x4E8E;&#x80FD;&#x591F;&#x4E3A;&#x6700;&#x574F;&#x60C5;&#x51B5;&#x63D0;&#x4F9B;O(log n)&#x7684;&#x65F6;&#x95F4;&#x590D;&#x6742;&#x5EA6;&#x6765;&#x8BF4;&#x662F;&#x5B8C;&#x5168;&#x503C;&#x5F97;&#x7684;&#x3002;&#x56E0;&#x6B64;&#xFF0C;&#x5728;</span></span><br><span class="line"><span class="comment">     * hashCode()&#x65B9;&#x6CD5;&#x8FD4;&#x56DE;&#x7684;&#x503C;&#x4E0D;&#x7BA1;&#x662F;&#x5206;&#x6563;&#x7684;&#x6216;&#x8005;&#x662F;&#x5171;&#x4EAB;&#x7684;&#x5076;&#x7136;&#x60C5;&#x51B5;&#x4E0B;&#x5F88;&#x5DEE;&#x6216;&#x8005;&#x6076;&#x610F;&#x4F7F;&#x7528;&#x7684;</span></span><br><span class="line"><span class="comment">     * &#x60C5;&#x51B5;&#x4E0B;&#xFF0C;&#x53EA;&#x8981;&#x90FD;&#x662F;&#x53EF;&#x6BD4;&#x8F83;&#x7684;&#xFF0C;&#x90FD;&#x80FD;&#x7F13;&#x548C;&#x6027;&#x80FD;&#x5F97;&#x5230;&#x6025;&#x5267;&#x4E0B;&#x964D;&#x3002;&#xFF08;&#x5982;&#x679C;&#x8FD9;&#x4E9B;&#x90FD;&#x4E0D;&#x9002;&#x7528;&#xFF0C;&#x4E0E;&#x4E0D;</span></span><br><span class="line"><span class="comment">     * &#x91C7;&#x53D6;&#x9884;&#x9632;&#x63AA;&#x65BD;&#x76F8;&#x6BD4;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x80FD;&#x5728;&#x65F6;&#x95F4;&#x548C;&#x7A7A;&#x95F4;&#x4E0A;&#x6D6A;&#x8D39;&#x5927;&#x7EA6;&#x4E24;&#x500D;&#x7684;&#x8D44;&#x6E90;&#x3002; &#x4F46;&#x662F;&#xFF0C;&#x552F;&#x4E00;&#x5DF2;&#x77E5;&#x7684;</span></span><br><span class="line"><span class="comment">     * &#x6848;&#x4F8B;&#x6E90;&#x4E8E;&#x7CDF;&#x7CD5;&#x7684;&#x7528;&#x6237;&#x7F16;&#x7A0B;&#x5B9E;&#x8DF5;&#xFF0C;&#x8FD9;&#x4E9B;&#x5B9E;&#x8DF5;&#x5DF2;&#x7ECF;&#x975E;&#x5E38;&#x7F13;&#x6162;&#xFF0C;&#x8FD9;&#x51E0;&#x4E4E;&#x6CA1;&#x6709;&#x4EC0;&#x4E48;&#x533A;&#x522B;&#x3002;&#xFF09;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * &#x56E0;&#x4E3A;&#x6811;&#x8282;&#x70B9;&#x5927;&#x7EA6;&#x76F8;&#x5F53;&#x4E8E;&#x666E;&#x901A;&#x8282;&#x70B9;&#x7684;&#x4E24;&#x500D;&#x5927;&#x5C0F;&#xFF0C;&#x6211;&#x4EEC;&#x53EA;&#x4F1A;&#x5728;&#x666E;&#x901A;&#x6876;&#x5305;&#x542B;&#x4E86;&#x8DB3;&#x591F;&#x591A;&#x7684;&#x8282;&#x70B9;&#x7684;&#x60C5;</span></span><br><span class="line"><span class="comment">     * &#x51B5;&#x4E0B;&#x624D;&#x4F1A;&#x4FDD;&#x8BC1;&#x4F7F;&#x7528;(&#x67E5;&#x770B; TREEIFY_THRESHOLD)&#x3002;&#x800C;&#x4E14;&#x5F53;&#x5B83;&#x4EEC;&#x9010;&#x6E10;&#x53D8;&#x5C0F;&#x7684;&#x65F6;&#x5019;&#xFF08;&#x7531;&#x4E8E;&#x5220;</span></span><br><span class="line"><span class="comment">     * &#x9664;&#x6216;&#x8005;&#x91CD;&#x65B0;&#x8C03;&#x6574;&#x5927;&#x5C0F;&#xFF09;&#xFF0C;&#x5C06;&#x4F1A;&#x8F6C;&#x5316;&#x56DE;&#x666E;&#x901A;&#x7684;&#x6876;&#x3002;&#x5728;&#x7528;&#x6237;&#x826F;&#x597D;&#x7684;&#x4F7F;&#x7528;hash&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#xFF0C;&#x6811;&#x6876;&#x57FA;</span></span><br><span class="line"><span class="comment">     * &#x672C;&#x5F88;&#x5C11;&#x88AB;&#x4F7F;&#x7528;&#x5230;&#x3002;&#x7406;&#x60F3;&#x60C5;&#x51B5;&#x4E0B;&#xFF0C;&#x5728;&#x968F;&#x673A;hashCodes&#x4E0B;&#xFF0C;&#x6876;&#x5185;&#x8282;&#x70B9;&#x7684;&#x9891;&#x7387;&#x9075;&#x5FAA;&#x6CCA;&#x677E;&#x5206;&#x5E03;</span></span><br><span class="line"><span class="comment">     * (https://zh.wikipedia.org/zh-hans/&#x6CCA;&#x677E;&#x5206;&#x5E03;)&#xFF0C;&#x53C2;&#x6570;&#x5E73;&#x5747;&#x503C;&#x7EA6;&#x4E3A;0.5&#xFF0C;&#x9ED8;&#x8BA4;&#x8C03;</span></span><br><span class="line"><span class="comment">     * &#x6574;&#x9608;&#x503C;&#x4E3A;0.75&#xFF0C;&#x5C3D;&#x7BA1;&#x7531;&#x4E8E;&#x8C03;&#x6574;&#x7C92;&#x5EA6;&#x4F1A;&#x5BFC;&#x81F4;&#x5927;&#x5DEE;&#x5F02;&#x3002;&#x5FFD;&#x7565;&#x8FD9;&#x4E2A;&#x5DEE;&#x5F02;&#xFF0C;&#x5217;&#x8868;&#x5927;&#x5C0F;&#x7684;&#x9884;&#x671F;&#x503C;&#x9075;&#x5FAA;</span></span><br><span class="line"><span class="comment">     * &#x516C;&#x5F0F; (exp(-0.5) * pow(0.5, k) / factorial(k))&#x3002;&#x7B2C;&#x4E00;&#x4E2A;&#x503C;&#x662F;&#xFF1A;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 0:    0.60653066</span></span><br><span class="line"><span class="comment">     * 1:    0.30326533</span></span><br><span class="line"><span class="comment">     * 2:    0.07581633</span></span><br><span class="line"><span class="comment">     * 3:    0.01263606</span></span><br><span class="line"><span class="comment">     * 4:    0.00157952</span></span><br><span class="line"><span class="comment">     * 5:    0.00015795</span></span><br><span class="line"><span class="comment">     * 6:    0.00001316</span></span><br><span class="line"><span class="comment">     * 7:    0.00000094</span></span><br><span class="line"><span class="comment">     * 8:    0.00000006</span></span><br><span class="line"><span class="comment">     * &#x66F4;&#x591A;&#xFF1A; &#x5C0F;&#x4E8E;&#x5343;&#x4E07;&#x5206;&#x4E4B;&#x4E00;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * &#x6811;&#x6876;&#x7684;&#x6839;&#x8282;&#x70B9;&#x901A;&#x5E38;&#x662F;&#x5B83;&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x8282;&#x70B9;&#x3002;&#x7136;&#x540E;&#xFF0C;&#x6709;&#x4E9B;&#x65F6;&#x5019;&#xFF08;&#x76EE;&#x524D;&#x53EA;&#x6709;&#x5728;Iterator.remove</span></span><br><span class="line"><span class="comment">     * &#x4E0A;&#x624D;&#x4F1A;&#x53D1;&#x751F;&#xFF09;&#xFF0C;&#x6839;&#x8282;&#x70B9;&#x53EF;&#x80FD;&#x5728;&#x5176;&#x4ED6;&#x5730;&#x65B9;&#xFF0C;&#x4F46;&#x662F;&#x53EF;&#x4EE5;&#x5728;&#x5728;&#x7236;&#x94FE;&#x63A5;&#x4E4B;&#x540E;&#x6062;&#x590D;&#xFF08;&#x65B9;&#x6CD5; TreeNode.root()&#xFF09;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * &#x6240;&#x6709;&#x9002;&#x7528;&#x7684;&#x5185;&#x90E8;&#x65B9;&#x6CD5;&#x90FD;&#x63A5;&#x53D7;hash code&#x503C;&#x4F5C;&#x4E3A;&#x53C2;&#x6570;&#xFF08;&#x901A;&#x5E38;&#x7531;public&#x65B9;&#x6CD5;&#x63D0;&#x4F9B;&#xFF09;&#xFF0C;&#x5141;&#x8BB8;&#x5B83;</span></span><br><span class="line"><span class="comment">     * &#x4EEC;&#x76F8;&#x4E92;&#x8C03;&#x7528;&#x800C;&#x4E0D;&#x9700;&#x8981;&#x91CD;&#x65B0;&#x8BA1;&#x7B97;&#x7528;&#x6237;hashCodes&#x503C;&#x3002;&#x5927;&#x591A;&#x6570;&#x7684;&#x5185;&#x90E8;&#x65B9;&#x6CD5;&#x4E5F;&#x63A5;&#x53D7;&#x4E00;&#x4E2A;&#x201C;tab&#x201D;&#x53C2;</span></span><br><span class="line"><span class="comment">     * &#x6570;&#xFF0C;&#x5B83;&#x901A;&#x5E38;&#x4EE3;&#x8868;&#x5F53;&#x524D;&#x7684;hash&#x8868;&#xFF0C;&#x4F46;&#x662F;&#x5728;&#x91CD;&#x65B0;&#x8C03;&#x6574;&#x5927;&#x5C0F;&#x6216;&#x8005;&#x6293;&#x82B1;&#x540E;&#x4E5F;&#x53EF;&#x80FD;&#x662F;&#x4E00;&#x4E2A;&#x65B0;&#x7684;&#x6216;&#x8005;&#x65E7;</span></span><br><span class="line"><span class="comment">     * &#x7684;hash&#x8868;&#x3002;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * &#x5F53;&#x6876;&#x7684;&#x8282;&#x70B9;list&#x88AB;&#x6811;&#x5316;&#xFF0C;&#x5206;&#x5272;&#x6216;&#x8005;&#x56DE;&#x5F52;&#x94FE;&#x8868;&#x540E;&#xFF0C;&#x6211;&#x4EEC;&#x5C06;&#x5B83;&#x4EEC;&#x4FDD;&#x6301;&#x5728;&#x76F8;&#x540C;&#x7684;&#x76F8;&#x5BF9;&#x8BBF;&#x95EE;/&#x904D;&#x5386;</span></span><br><span class="line"><span class="comment">     * &#x987A;&#x5E8F;&#xFF08;&#x5373;&#x5B57;&#x6BB5;Node.next&#xFF09;&#x4E2D;&#x4EE5;&#x66F4;&#x597D;&#x5730;&#x4FDD;&#x7559;&#x5C40;&#x90E8;&#x6027;&#xFF0C;&#x5E76;&#x7565;&#x5FAE;&#x7B80;&#x5316;&#x8C03;&#x7528;iterator.remove</span></span><br><span class="line"><span class="comment">     * &#x7684;&#x62C6;&#x5206;&#x548C;&#x904D;&#x5386;&#x7684;&#x5904;&#x7406;&#x3002;&#x5F53;&#x5728;&#x63D2;&#x5165;&#x4E2D;&#x4F7F;&#x7528;&#x6BD4;&#x8F83;&#x5668;&#xFF0C;&#x4E3A;&#x4E86;&#x4FDD;&#x8BC1;&#x91CD;&#x65B0;&#x6392;&#x5E8F;&#x7684;&#x987A;&#x5E8F;&#xFF08;&#x6216;&#x8005;&#x5C3D;&#x53EF;&#x80FD;&#x63A5;</span></span><br><span class="line"><span class="comment">     * &#x8FD1;&#xFF09;&#xFF0C;&#x6211;&#x4EEC;&#x5C06;&#x7C7B;&#x548C;identityHashCodes&#x4F5C;&#x4E3A;&#x7ED1;&#x5B9A;&#x5668;&#x8FDB;&#x884C;&#x6BD4;&#x8F83;&#x3002;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * &#x666E;&#x901A;&#x548C;&#x6811;&#x6A21;&#x5F0F;&#x4E4B;&#x95F4;&#x7684;&#x4F7F;&#x7528;&#x548C;&#x8F6C;&#x5316;&#x7531;&#x4E8E;&#x5B50;&#x7C7B;LinkedHashMap&#x7684;&#x5B58;&#x5728;&#x800C;&#x53D8;&#x5F97;&#x590D;&#x6742;&#x3002;&#x8BF7;&#x53C2;&#x9605;&#x4E0B;</span></span><br><span class="line"><span class="comment">     * &#x9762;&#x7684;hook&#x65B9;&#x6CD5;&#xFF0C;&#x8FD9;&#x4E9B;hook&#x65B9;&#x6CD5;&#x5B9A;&#x4E49;&#x4E3A;&#x5728;&#x63D2;&#x5165;&#xFF0C;&#x5220;&#x9664;&#x548C;&#x8BBF;&#x95EE;&#x65F6;&#x8C03;&#x7528;&#xFF0C;&#x5141;&#x8BB8;LinkedHashMap</span></span><br><span class="line"><span class="comment">     * &#x5185;&#x90E8;&#x4EE5;&#x5176;&#x4ED6;&#x65B9;&#x5F0F;&#x4FDD;&#x6301;&#x72EC;&#x7ACB;&#x4E8E;&#x8FD9;&#x4E9B;&#x673A;&#x5236;&#xFF08;&#x666E;&#x901A;&#x548C;&#x6811;&#x6A21;&#x5F0F;&#x7684;&#x8F6C;&#x5316;&#x903B;&#x8F91;&#xFF09;&#x3002;&#xFF08;&#x8FD9;&#x4E5F;&#x5C31;&#x9700;&#x8981;&#x5C06;map&#x5B9E;</span></span><br><span class="line"><span class="comment">     * &#x4F8B;&#x4F20;&#x9012;&#x7ED9;&#x53EF;&#x80FD;&#x521B;&#x5EFA;&#x65B0;&#x8282;&#x70B9;&#x7684;&#x4E00;&#x4E9B;&#x5DE5;&#x5177;&#x65B9;&#x6CD5;&#x4E2D;&#x3002;&#xFF09;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * The concurrent-programming-like SSA-based coding style helps</span></span><br><span class="line"><span class="comment">     * avoid aliasing errors amid all of the twisty pointer operations.</span></span><br><span class="line"><span class="comment">     * (TODO &#x6CA1;&#x660E;&#x767D;&#x8FD9;&#x53E5;&#x8BDD;&#x5565;&#x610F;&#x601D;&#xFF0C;&#x4F3C;&#x4E4E;&#x662F;&#x8DDF;SSA&#x7F16;&#x7801;&#x98CE;&#x683C;&#x6709;&#x5173;&#xFF0C;&#x4F46;&#x662F;&#x8C37;&#x6B4C;&#x4E86;&#x4E00;&#x4E0B;&#xFF0C;&#x6CA1;&#x627E;&#x5230;&#x8FD9;&#x79CD;</span></span><br><span class="line"><span class="comment">     * &#x7F16;&#x7801;&#x98CE;&#x683C;&#x3002;&#x4EE5;&#x540E;&#x4E86;&#x89E3;&#x4E86;&#xFF0C;&#x518D;&#x5728;&#x8FD9;&#x91CC;&#x505A;&#x8865;&#x5145;&#x8BF4;&#x660E;)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x9ED8;&#x8BA4;&#x7684;&#x521D;&#x59CB;&#x5316;&#x5BB9;&#x91CF; - &#x5FC5;&#x987B;&#x662F;2&#x7684;&#x6307;&#x6570;&#x7EA7;&#x3002;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> DEFAULT_INITIAL_CAPACITY = <span class="number">1</span> &lt;&lt; <span class="number">4</span>; <span class="comment">// &#x540C;&#x7B49; 16</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x6700;&#x5927;&#x5141;&#x8BB8;&#x5BB9;&#x91CF;, &#x5F53;&#x663E;&#x793A;&#x6307;&#x5B9A;&#x4E3A;&#x5176;&#x4E2D;&#x4E00;&#x4E2A;&#x6784;&#x9020;&#x5668;&#x7684;&#x53C2;&#x6570;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x8FD9;&#x4E2A;&#x503C;&#x5C06;&#x4F1A;&#x88AB;&#x4F7F;&#x7528;</span></span><br><span class="line"><span class="comment">     * &#x5FC5;&#x987B;&#x4E3A;2&#x7684;&#x6307;&#x6570;&#x7EA7; &lt;= 1&lt;&lt;30.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> MAXIMUM_CAPACITY = <span class="number">1</span> &lt;&lt; <span class="number">30</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5F53;&#x6784;&#x9020;&#x5668;&#x672A;&#x6307;&#x5B9A;&#x7684;&#x65F6;&#x5019;&#x4F7F;&#x7528;&#x7684;&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;&#x503C;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">float</span> DEFAULT_LOAD_FACTOR = <span class="number">0.75f</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x6876;&#x7684;&#x8282;&#x70B9;&#x6570;&#x91CF;&#xFF0C;&#x7528;&#x4E8E;&#x5224;&#x65AD;&#x4F55;&#x65F6;&#x4F7F;&#x7528;&#x6570;&#x800C;&#x4E0D;&#x662F;&#x8282;&#x70B9;&#x94FE;&#x8868;&#x3002;&#x5F53;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x88AB;&#x6DFB;&#x52A0;&#x5230;&#x6876;&#x7684;&#x65F6;</span></span><br><span class="line"><span class="comment">     * &#x5019;&#xFF0C;&#x5982;&#x679C;&#x8282;&#x70B9;&#x6570;&#x91CF;&#x8FBE;&#x5230;&#x8FD9;&#x4E2A;&#x9608;&#x503C;&#xFF0C;&#x90A3;&#x4E48;&#x8282;&#x70B9;&#x5C06;&#x88AB;&#x8F6C;&#x5316;&#x4E3A;&#x6811;&#x3002;&#x8FD9;&#x4E2A;&#x503C;&#x5FC5;&#x987B;&#x5927;&#x4E8E;2&#x5E76;&#x4E14;</span></span><br><span class="line"><span class="comment">     * &#x81F3;&#x5C11;&#x4E3A;8&#x6765;&#x4F7F;&#x5F97;&#x5728;&#x6811;&#x5220;&#x9664;&#x64CD;&#x4F5C;&#x540E;&#x6536;&#x7F29;&#x56DE;&#x666E;&#x901A;&#x6876;&#xFF08;TODO &#x6709;&#x5F85;&#x7814;&#x7A76;&#xFF0C;&#x53EF;&#x80FD;&#x7B14;&#x8005;&#x7FFB;&#x8BD1;&#x7684;&#x6709;&#x95EE;&#x9898;&#xFF09;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TREEIFY_THRESHOLD = <span class="number">8</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5728;&#x91CD;&#x65B0;&#x8C03;&#x6574;&#x5927;&#x5C0F;&#x7684;&#x64CD;&#x4F5C;&#x5185;&#xFF0C;&#x6876;&#x5185;&#x8282;&#x70B9;&#x4ECE;&#x6811;&#x6536;&#x7F29;&#x56DE;&#x94FE;&#x8868;&#x7684;&#x4E00;&#x4E2A;&#x6570;&#x91CF;&#x9608;&#x503C;&#x3002;&#x5E94;&#x8BE5;&#x5C0F;&#x4E8E; </span></span><br><span class="line"><span class="comment">     * TREEIFY_THRESHOLD &#x503C;&#xFF0C;&#x5E76;&#x4E14;&#x81F3;&#x5C11;&#x4E3A;6&#x6765;&#x4F7F;&#x5F97;&#x5728;&#x5220;&#x9664;&#x64CD;&#x4F5C;&#x4E0B;&#x6536;&#x7F29;&#x56DE;&#x94FE;&#x8868;&#x6570;&#x7EC4;&#x3002;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> UNTREEIFY_THRESHOLD = <span class="number">6</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x6700;&#x5C0F;&#x7684;hash&#x8868;&#x5BB9;&#x91CF;&#x9608;&#x503C;&#x7528;&#x4E8E;&#x5224;&#x65AD;&#x6876;&#x662F;&#x5426;&#x5E94;&#x8BE5;&#x6811;&#x5316;&#x3002;&#xFF08;&#x5426;&#x5219;hash&#x8868;&#x5C06;&#x88AB;&#x91CD;&#x65B0;&#x8C03;&#x6574;&#x5927;</span></span><br><span class="line"><span class="comment">     * &#x5C0F;&#x5982;&#x679C;&#x6709;&#x592A;&#x591A;&#x7684;&#x8282;&#x70B9;&#x5728;&#x6876;&#x5185;&#x3002;&#xFF09; &#x8FD9;&#x4E2A;&#x503C;&#x81F3;&#x5C11;&#x5E94;&#x8BE5;&#x4E3A;4 * TREEIFY_THRESHOLD </span></span><br><span class="line"><span class="comment">     * &#x7684;&#x6570;&#x503C;&#x6765;&#x907F;&#x514D;&#x8C03;&#x6574;&#x5927;&#x5C0F;&#x7684;&#x9608;&#x503C;&#x548C;&#x6811;&#x5316;&#x7684;&#x9608;&#x503C;&#x4E4B;&#x95F4;&#x7684;&#x51B2;&#x7A81;&#x3002;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> MIN_TREEIFY_CAPACITY = <span class="number">64</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x6876;&#x5185;&#x6700;&#x57FA;&#x672C;&#x7684;&#x8282;&#x70B9;&#xFF0C;&#x7528;&#x4E8E;&#x5927;&#x591A;&#x6570;&#x7684;&#x952E;&#x503C;&#x5BF9;&#x3002;&#xFF08;&#x8BF7;&#x53C2;&#x9605; TreeNode &#x5B50;&#x7C7B;&#xFF0C;&#x548C;&#x5728; </span></span><br><span class="line"><span class="comment">     * LinkedHashMap &#x7C7B;&#x4E2D;&#x5B83;&#x7684; Entry &#x5B50;&#x7C7B;&#x3002;&#xFF09;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Node</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt; <span class="keyword">implements</span> <span class="title">Map</span>.<span class="title">Entry</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt; </span>{</span><br><span class="line">        <span class="keyword">final</span> <span class="keyword">int</span> hash;</span><br><span class="line">        <span class="keyword">final</span> K key;</span><br><span class="line">        V value;</span><br><span class="line">        Node&lt;K,V&gt; next;</span><br><span class="line"></span><br><span class="line">        Node(<span class="keyword">int</span> hash, K key, V value, Node&lt;K,V&gt; next) {</span><br><span class="line">            <span class="keyword">this</span>.hash = hash;</span><br><span class="line">            <span class="keyword">this</span>.key = key;</span><br><span class="line">            <span class="keyword">this</span>.value = value;</span><br><span class="line">            <span class="keyword">this</span>.next = next;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> K <span class="title">getKey</span><span class="params">()</span>        </span>{ <span class="keyword">return</span> key; }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> V <span class="title">getValue</span><span class="params">()</span>      </span>{ <span class="keyword">return</span> value; }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> String <span class="title">toString</span><span class="params">()</span> </span>{ <span class="keyword">return</span> key + <span class="string">&quot;=&quot;</span> + value; }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">int</span> <span class="title">hashCode</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">return</span> Objects.hashCode(key) ^ Objects.hashCode(value);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> V <span class="title">setValue</span><span class="params">(V newValue)</span> </span>{</span><br><span class="line">            V oldValue = value;</span><br><span class="line">            value = newValue;</span><br><span class="line">            <span class="keyword">return</span> oldValue;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">boolean</span> <span class="title">equals</span><span class="params">(Object o)</span> </span>{</span><br><span class="line">            <span class="keyword">if</span> (o == <span class="keyword">this</span>)</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            <span class="keyword">if</span> (o <span class="keyword">instanceof</span> Map.Entry) {</span><br><span class="line">                Map.Entry&lt;?,?&gt; e = (Map.Entry&lt;?,?&gt;)o;</span><br><span class="line">                <span class="keyword">if</span> (Objects.equals(key, e.getKey()) &amp;&amp;</span><br><span class="line">                    Objects.equals(value, e.getValue()))</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ---------------- &#x9759;&#x6001;&#x5DE5;&#x5177;&#x7C7B;&#x65B9;&#x6CD5; -------------- */</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x8BA1;&#x7B97;key&#x7684;hashCode&#x503C;&#x5E76;&#x4E14;&#x5F02;&#x6216;hash&#x503C;&#x7684;&#x9AD8;16&#x4F4D;&#x3002;&#x56E0;&#x4E3A;hash&#x8868;&#x7528;&#x4E86;2&#x7684;&#x6307;&#x6570;&#x7EA7;&#x6570;&#x503C;</span></span><br><span class="line"><span class="comment">     * &#x4F5C;&#x4E3A;&#x63A9;&#x7801;&#xFF0C;&#x53EA;&#x6709;&#x9AD8;&#x4E8E;&#x5F53;&#x524D;&#x63A9;&#x7801;&#x957F;&#x5EA6;&#x7684;&#x4F4D;&#x4F1A;&#x53D8;&#x5316;&#x7684; hash &#x6765;&#x8BF4;&#xFF0C;&#x8BA1;&#x7B97;&#x51FA;&#x6765;&#x6570;&#x7EC4;&#x4E0B;&#x6807;&#x5C31;&#x4F1A;</span></span><br><span class="line"><span class="comment">     * &#x5168;&#x90E8;&#x51B2;&#x7A81;&#xFF08;&#x5176;&#x4E2D;&#x4E00;&#x79CD;&#x5DF2;&#x77E5;&#x7684;&#x4E00;&#x79CD;&#x60C5;&#x51B5;&#x662F; Float &#x4F5C;&#x4E3A; key&#xFF0C;&#x5E76;&#x4E14;&#x6309;&#x7167;&#x81EA;&#x7136;&#x6570;&#x987A;&#x5E8F;&#x9012;&#x589E;</span></span><br><span class="line"><span class="comment">     * &#x7684;&#x5B58;&#x5165;&#x4E00;&#x4E2A;&#x5C0F;&#x5C3A;&#x5BF8;&#x7684;table&#x6570;&#x7EC4;&#x4E2D;&#xFF09;&#x6240;&#x4EE5;&#x6211;&#x4EEC;&#x5E94;&#x7528;&#x4E86;&#x4E00;&#x4E2A;&#x8F6C;&#x5316;&#x4F7F;&#x5F97;&#x5C06;&#x9AD8;&#x4F4D;&#x7684;&#x5F71;&#x54CD;&#x8F6C;&#x79FB;</span></span><br><span class="line"><span class="comment">     * &#x5230;&#x4F4E;&#x4F4D;&#x3002;&#x8FD9;&#x662F;&#x57FA;&#x4E8E;&#x901F;&#x5EA6;&#x3001;&#x6548;&#x7387;&#x548C;&#x4F4D;&#x6269;&#x5C55;&#x8D28;&#x91CF;&#x7684;&#x4E00;&#x79CD;&#x6743;&#x8861;&#x3002;&#x56E0;&#x4E3A;&#x8BB8;&#x591A;&#x5E38;&#x89C1;&#x7684; hash &#x503C;&#x90FD;</span></span><br><span class="line"><span class="comment">     * &#x662F;&#x9002;&#x5EA6;&#x5206;&#x6563;&#x7684;&#xFF08;&#x56E0;&#x6B64;&#x4F4D;&#x6269;&#x6563;&#x7684;&#x6536;&#x76CA;&#x4E0D;&#x5927;&#xFF09;&#xFF0C;&#x53C8;&#x56E0;&#x4E3A;&#x6211;&#x4EEC;&#x4F7F;&#x7528;&#x6811;&#xFF0C;&#x6765;&#x7BA1;&#x63A7;&#x5927;&#x6570;&#x91CF;&#x7684;&#x51B2;&#x7A81;</span></span><br><span class="line"><span class="comment">     * &#x5143;&#x7D20;&#x3002;&#x4F7F;&#x7528;XOR&#x5F02;&#x6216;&#x8FD0;&#x7B97;&#x6765;&#x79FB;&#x4F4D;&#xFF0C;&#x53EF;&#x4EE5;&#x5C3D;&#x53EF;&#x80FD;&#x4F4E;&#x6210;&#x672C;&#x5730;&#x51CF;&#x5C11;&#x7CFB;&#x7EDF;&#x6027;&#x635F;&#x8017;&#xFF0C;&#x4E5F;&#x5C06;&#x539F;&#x672C;&#x4E0D;&#x53C2;</span></span><br><span class="line"><span class="comment">     * &#x4E0E;&#x6570;&#x7EC4;&#x4E0B;&#x6807;&#x8BA1;&#x7B97;&#x7684;&#x9AD8;&#x4F4D;&#x7684;&#x4E5F;&#x7ED9;&#x5305;&#x542B;&#x8FDB;&#x6765;&#x4E86;&#x3002;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> <span class="title">hash</span><span class="params">(Object key)</span> </span>{</span><br><span class="line">        <span class="keyword">int</span> h;</span><br><span class="line">        <span class="keyword">return</span> (key == <span class="keyword">null</span>) ? <span class="number">0</span> : (h = key.hashCode()) ^ (h &gt;&gt;&gt; <span class="number">16</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5982;&#x679C;&#x8FD9;&#x4E2A;&#x7C7B;&#x662F;&quot;class C implements Comparable&lt;C&gt;&quot;&#x7684;&#x5F62;&#x5F0F;&#xFF0C;&#x5219;&#x8FD4;&#x56DE;x&#x7684;&#x7C7B;&#xFF0C;</span></span><br><span class="line"><span class="comment">     * &#x5426;&#x5219;&#x8FD4;&#x56DE;null</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> Class&lt;?&gt; comparableClassFor(Object x) {</span><br><span class="line">        <span class="keyword">if</span> (x <span class="keyword">instanceof</span> Comparable) {</span><br><span class="line">            Class&lt;?&gt; c; Type[] ts, as; Type t; ParameterizedType p;</span><br><span class="line">            <span class="keyword">if</span> ((c = x.getClass()) == String.class) <span class="comment">// &#x901A;&#x8FC7;&#x68C0;&#x67E5;</span></span><br><span class="line">                <span class="keyword">return</span> c;</span><br><span class="line">            <span class="keyword">if</span> ((ts = c.getGenericInterfaces()) != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; ts.length; ++i) {</span><br><span class="line">                    <span class="keyword">if</span> (((t = ts[i]) <span class="keyword">instanceof</span> ParameterizedType) &amp;&amp;</span><br><span class="line">                        ((p = (ParameterizedType)t).getRawType() ==</span><br><span class="line">                         Comparable.class) &amp;&amp;</span><br><span class="line">                        (as = p.getActualTypeArguments()) != <span class="keyword">null</span> &amp;&amp;</span><br><span class="line">                        as.length == <span class="number">1</span> &amp;&amp; as[<span class="number">0</span>] == c) <span class="comment">// &#x53C2;&#x6570;&#x7C7B;&#x578B;&#x662F;c</span></span><br><span class="line">                        <span class="keyword">return</span> c;</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5982;&#x679C;x&#x5339;&#x914D;kc&#xFF08;k&#x7684;&#x6839;&#x636E;&#x6BD4;&#x8F83;&#x7B5B;&#x9009;&#x540E;&#x7B26;&#x5408;&#x7684;&#x7C7B;&#xFF09;&#x8FD4;&#x56DE; k.compareTo(x) &#x7684;&#x503C;&#xFF0C;&#x5426;&#x5219;&#x8FD4;&#x56DE;0&#x3002;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@SuppressWarnings</span>({<span class="string">&quot;rawtypes&quot;</span>,<span class="string">&quot;unchecked&quot;</span>}) <span class="comment">// &#x5F3A;&#x8F6C;&#x4E3A;&#x53EF;&#x6BD4;&#x8F83;&#x7684;</span></span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">compareComparables</span><span class="params">(Class&lt;?&gt; kc, Object k, Object x)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> (x == <span class="keyword">null</span> || x.getClass() != kc ? <span class="number">0</span> :</span><br><span class="line">                ((Comparable)k).compareTo(x));</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x6839;&#x636E;&#x7ED9;&#x5B9A;&#x7684;&#x5BB9;&#x91CF;&#x503C;&#x8FD4;&#x56DE;&#x6700;&#x63A5;&#x8FD1;&#x7684;2&#x6B21;&#x65B9;&#x6570;&#x503C;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> <span class="title">tableSizeFor</span><span class="params">(<span class="keyword">int</span> cap)</span> </span>{</span><br><span class="line">        <span class="keyword">int</span> n = cap - <span class="number">1</span>;</span><br><span class="line">        n |= n &gt;&gt;&gt; <span class="number">1</span>;</span><br><span class="line">        n |= n &gt;&gt;&gt; <span class="number">2</span>;</span><br><span class="line">        n |= n &gt;&gt;&gt; <span class="number">4</span>;</span><br><span class="line">        n |= n &gt;&gt;&gt; <span class="number">8</span>;</span><br><span class="line">        n |= n &gt;&gt;&gt; <span class="number">16</span>;</span><br><span class="line">        <span class="keyword">return</span> (n &lt; <span class="number">0</span>) ? <span class="number">1</span> : (n &gt;= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + <span class="number">1</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ---------------- &#x5C5E;&#x6027; -------------- */</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * table&#xFF0C;&#x7B2C;&#x4E00;&#x6B21;&#x4F7F;&#x7528;&#x7684;&#x65F6;&#x5019;&#x521D;&#x59CB;&#x5316;&#xFF0C;&#x5E76;&#x4E14;&#x5728;&#x5FC5;&#x8981;&#x7684;&#x65F6;&#x5019;&#x8C03;&#x6574;&#x5927;&#x5C0F;&#x3002;&#x5F53;&#x7533;&#x8BF7;&#x540E;&#xFF0C;&#x957F;&#x5EA6;&#x6C38;&#x8FDC;</span></span><br><span class="line"><span class="comment">     * &#x90FD;&#x662F;2&#x7684;&#x6B21;&#x65B9;&#x3002;&#xFF08;&#x6211;&#x4EEC;&#x8FD8;&#x5728;&#x4E00;&#x4E9B;&#x64CD;&#x4F5C;&#x4E2D;&#x5BB9;&#x5FCD;&#x957F;&#x5EA6;&#x4E3A;&#x96F6;&#xFF0C;&#x4EE5;&#x5141;&#x8BB8;&#x5F53;&#x524D;&#x4E0D;&#x9700;&#x8981;&#x7684;&#x521D;&#x59CB;&#x5316;&#x673A;&#x5236;&#x3002;&#xFF09;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">transient</span> Node&lt;K,V&gt;[] table;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x7F13;&#x5B58;entrySet()&#x7684;&#x7ED3;&#x679C;&#x96C6;&#x3002;&#x6CE8;&#x610F; AbstractMap &#x7528;&#x6765;&#x5C06;&#x5C5E;&#x6027;&#x7528;&#x4E8E; keySet() &#x548C; values()</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">transient</span> Set&lt;Map.Entry&lt;K,V&gt;&gt; entrySet;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5305;&#x542B;&#x5728;&#x8FD9;&#x4E2A;map&#x91CC;&#x9762;&#x7684;&#x952E;&#x503C;&#x5BF9;&#x6570;&#x91CF;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">transient</span> <span class="keyword">int</span> size;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * HashMap&#x5DF2;&#x7ECF;&#x88AB;&#x7ED3;&#x6784;&#x5316;&#x4FEE;&#x6539;&#x7684;&#x6B21;&#x6570;</span></span><br><span class="line"><span class="comment">     * &#x5728;HashMap&#x5185;&#x66F4;&#x6539;&#x952E;&#x503C;&#x5BF9;&#x6570;&#x91CF;&#x6216;&#x8005;&#x4FEE;&#x6539;&#x5B83;&#x5185;&#x90E8;&#x7ED3;&#x6784;&#xFF08;&#x4E3E;&#x4E2A;&#x4F8B;&#x5B50;&#xFF1A;&#x91CD;&#x65B0;hash&#xFF09;&#x7684;&#x64CD;&#x4F5C;&#x88AB;&#x79F0;</span></span><br><span class="line"><span class="comment">     * &#x4E3A;&#x7ED3;&#x6784;&#x5316;&#x4FEE;&#x6539;&#x3002;&#x8FD9;&#x4E2A;&#x5C5E;&#x6027;&#x662F;&#x7528;&#x6765;&#x4F7F;&#x5F97;HashMap&#x7684;&#x89C6;&#x56FE;&#x96C6;&#x5408;&#x5728;&#x8FED;&#x4EE3;&#x7684;&#x65F6;&#x5019;&#x5FEB;&#x901F;&#x5931;&#x8D25;&#x7528;&#x7684;&#x3002;</span></span><br><span class="line"><span class="comment">     * &#xFF08;&#x8BF7;&#x53C2;&#x9605; ConcurrentModificationException &#x5F02;&#x5E38;&#xFF09;&#x3002;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">transient</span> <span class="keyword">int</span> modCount;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x4E0B;&#x6B21;&#x6269;&#x5BB9;&#x7684;&#x5927;&#x5C0F;&#x9608;&#x503C;&#xFF08;&#x5BB9;&#x91CF; * &#x8D1F;&#x8F7D;&#x56E0;&#x5B50;&#xFF09;&#x3002;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@serial</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="comment">// (The javadoc description is true upon serialization.</span></span><br><span class="line">    <span class="comment">// Additionally, if the table array has not been allocated, this</span></span><br><span class="line">    <span class="comment">// field holds the initial array capacity, or zero signifying</span></span><br><span class="line">    <span class="comment">// DEFAULT_INITIAL_CAPACITY.)</span></span><br><span class="line">    <span class="keyword">int</span> threshold;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * hash&#x8868;&#x7684;&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@serial</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">final</span> <span class="keyword">float</span> loadFactor;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ---------------- &#x516C;&#x6709;&#x65B9;&#x6CD5; -------------- */</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x6784;&#x9020;&#x4E00;&#x4E2A;&#x7A7A;&#x7684;&#x6307;&#x5B9A;&#x5BB9;&#x91CF;&#x548C;&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;&#x7684; &lt;tt&gt;HashMap&lt;/tt&gt; </span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span>  initialCapacity &#x521D;&#x59CB;&#x5316;&#x5BB9;&#x91CF;&#x5927;&#x5C0F;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span>  loadFactor      &#x8D1F;&#x8F7D;&#x56E0;&#x5B50;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalArgumentException &#x5982;&#x679C;&#x521D;&#x59CB;&#x5316;&#x5BB9;&#x91CF;&#x5927;&#x5C0F;&#x5C0F;&#x4E8E;0&#x6216;&#x8005;&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;&#x4E0D;&#x4E3A;&#x5927;&#x4E8E;0&#x7684;&#x6B63;&#x6570;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">HashMap</span><span class="params">(<span class="keyword">int</span> initialCapacity, <span class="keyword">float</span> loadFactor)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (initialCapacity &lt; <span class="number">0</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">&quot;Illegal initial capacity: &quot;</span> +</span><br><span class="line">                                               initialCapacity);</span><br><span class="line">        <span class="keyword">if</span> (initialCapacity &gt; MAXIMUM_CAPACITY)</span><br><span class="line">            initialCapacity = MAXIMUM_CAPACITY;</span><br><span class="line">        <span class="keyword">if</span> (loadFactor &lt;= <span class="number">0</span> || Float.isNaN(loadFactor))</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">&quot;Illegal load factor: &quot;</span> +</span><br><span class="line">                                               loadFactor);</span><br><span class="line">        <span class="keyword">this</span>.loadFactor = loadFactor;</span><br><span class="line">        <span class="keyword">this</span>.threshold = tableSizeFor(initialCapacity);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x6784;&#x9020;&#x4E00;&#x4E2A;&#x7A7A;&#x7684;&#x6307;&#x5B9A;&#x5BB9;&#x91CF;&#x7684; &lt;tt&gt;HashMap&lt;/tt&gt;&#xFF0C;&#x9ED8;&#x8BA4;&#x8D1F;&#x8F7D;&#x5370;&#x5728;&#x4E3A;0.75</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span>  initialCapacity &#x521D;&#x59CB;&#x5316;&#x5BB9;&#x91CF;&#x5927;&#x5C0F;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalArgumentException &#x5982;&#x679C;&#x521D;&#x59CB;&#x5316;&#x5BB9;&#x91CF;&#x4E3A;&#x8D1F;&#x6570;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">HashMap</span><span class="params">(<span class="keyword">int</span> initialCapacity)</span> </span>{</span><br><span class="line">        <span class="keyword">this</span>(initialCapacity, DEFAULT_LOAD_FACTOR);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x6784;&#x9020;&#x4E00;&#x4E2A;&#x7A7A;&#x7684; &lt;tt&gt;HashMap&lt;/tt&gt;&#xFF0C; &#x4F7F;&#x7528;&#x9ED8;&#x8BA4;&#x7684;&#x521D;&#x59CB;&#x5BB9;&#x91CF;&#xFF08;16&#xFF09;&#x548C;&#x9ED8;&#x8BA4;&#x7684;&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;&#xFF08;0.75&#xFF09;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">HashMap</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">this</span>.loadFactor = DEFAULT_LOAD_FACTOR; <span class="comment">// &#x6240;&#x6709;&#x5176;&#x4ED6;&#x5C5E;&#x6027;&#x503C;&#x9ED8;&#x8BA4;</span></span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x7528;&#x76F8;&#x540C;&#x7684;&#x6620;&#x5C04;&#x7C7B; &lt;tt&gt;Map&lt;/tt&gt; &#x6784;&#x9020;&#x4E00;&#x4E2A;&#x65B0;&#x7684; &lt;tt&gt;HashMap&lt;/tt&gt; &#x3002;&lt;tt&gt;HashMap&lt;/tt&gt; &#x88AB;&#x521B;&#x5EFA;&#x4E3A;&#x9ED8;&#x8BA4;&#x7684;&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;&#xFF08;0.75&#xFF09;&#x5E76;&#x4E14;&#x4F7F;&#x7528;&#x6307;&#x5B9A;&#x7684; &lt;tt&gt;Map&lt;/tt&gt; &#x7684;&#x952E;&#x503C;&#x5BF9;&#x5927;&#x5C0F;&#x4F5C;&#x4E3A;&#x521D;&#x59CB;&#x5BB9;&#x91CF;&#x3002;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span>   m &#x6240;&#x5C5E;&#x952E;&#x503C;&#x5BF9;&#x5C06;&#x88AB;&#x653E;&#x5230;&#x521B;&#x5EFA;&#x7684;hashmap&#x5185;&#x7684;map</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span>  NullPointerException &#x5982;&#x679C;&#x6307;&#x5B9A;&#x4F20;&#x5165;&#x7684;map&#x4E3A;&#x7A7A;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">HashMap</span><span class="params">(Map&lt;? extends K, ? extends V&gt; m)</span> </span>{</span><br><span class="line">        <span class="keyword">this</span>.loadFactor = DEFAULT_LOAD_FACTOR;</span><br><span class="line">        putMapEntries(m, <span class="keyword">false</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x7EC6;&#x5B9E;&#x7EBF; Map.putAll &#x548C; Map &#x6784;&#x9020;&#x5668;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> m map&#x5B9E;&#x4F8B;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> evict &#x5F53;&#x521D;&#x59CB;&#x5316;&#x7684;&#x65F6;&#x5019;&#x4E3A;false&#xFF0C;&#x5426;&#x5219;&#x4E3A;true&#xFF08;&#x4F9D;&#x8D56;&#x4E8E; afterNodeInsertion &#x65B9;&#x6CD5;&#xFF09;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">final</span> <span class="keyword">void</span> <span class="title">putMapEntries</span><span class="params">(Map&lt;? extends K, ? extends V&gt; m, <span class="keyword">boolean</span> evict)</span> </span>{</span><br><span class="line">        <span class="keyword">int</span> s = m.size();</span><br><span class="line">        <span class="keyword">if</span> (s &gt; <span class="number">0</span>) {</span><br><span class="line">            <span class="keyword">if</span> (table == <span class="keyword">null</span>) { <span class="comment">// &#x9884;&#x5904;&#x7406;&#x5927;&#x5C0F;&#xFF0C;&#x672A;&#x521D;&#x59CB;&#x5316;</span></span><br><span class="line">                <span class="keyword">float</span> ft = ((<span class="keyword">float</span>)s / loadFactor) + <span class="number">1.0F</span>;</span><br><span class="line">                <span class="keyword">int</span> t = ((ft &lt; (<span class="keyword">float</span>)MAXIMUM_CAPACITY) ?</span><br><span class="line">                         (<span class="keyword">int</span>)ft : MAXIMUM_CAPACITY);</span><br><span class="line">                <span class="keyword">if</span> (t &gt; threshold)</span><br><span class="line">                    threshold = tableSizeFor(t);</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> (s &gt; threshold)</span><br><span class="line">                resize();</span><br><span class="line">            <span class="keyword">for</span> (Map.Entry&lt;? extends K, ? extends V&gt; e : m.entrySet()) {</span><br><span class="line">                K key = e.getKey();</span><br><span class="line">                V value = e.getValue();</span><br><span class="line">                putVal(hash(key), key, value, <span class="keyword">false</span>, evict);</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5728;&#x8FD9;&#x4E2A;map&#x5185;&#x7684;&#x952E;&#x503C;&#x5BF9;&#x6570;&#x91CF;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#x5728;&#x8FD9;&#x4E2A;map&#x5185;&#x7684;&#x952E;&#x503C;&#x5BF9;&#x6570;&#x91CF;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">size</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> size;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5982;&#x679C;&#x8FD9;&#x4E2A;map&#x6CA1;&#x6709;&#x5305;&#x542B;&#x952E;&#x503C;&#x5BF9;&#xFF0C;&#x8FD4;&#x56DE; &lt;tt&gt;true&lt;/tt&gt;&#x3002;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#x5982;&#x679C;&#x8FD9;&#x4E2A;map&#x6CA1;&#x6709;&#x5305;&#x542B;&#x952E;&#x503C;&#x5BF9;&#x5219;&#x4E3A; &lt;tt&gt;true&lt;/tt&gt;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isEmpty</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> size == <span class="number">0</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x8FD4;&#x56DE;&#x6307;&#x5B9A;key&#x6620;&#x5C04;&#x7684;&#x503C;&#xFF0C;&#x6216;&#x8005;&#x5982;&#x679C;&#x8FD9;&#x4E2A;map&#x4E0D;&#x5305;&#x542B;&#x8FD9;&#x4E2A;key&#x5219;&#x8FD4;&#x56DE; {<span class="doctag">@code</span> null}</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * &lt;p&gt;&#x66F4;&#x6B63;&#x5F0F;&#x7684;&#x8BF4;&#xFF0C;&#x5982;&#x679C;&#x8FD9;&#x4E2A;map&#x5305;&#x542B;&#x4E86;&#x4ECE;&#x4E00;&#x4E2A;key {<span class="doctag">@code</span> k} &#x5230;&#x4E00;&#x4E2A;&#x503C; {<span class="doctag">@code</span> v} </span></span><br><span class="line"><span class="comment">     * &#x4EE5;&#x4F7F;&#x5F97; {<span class="doctag">@code</span> (key==null ? k==null : key.equals(k))} &#x6210;&#x7ACB;&#xFF0C;&#x90A3;&#x4E48;</span></span><br><span class="line"><span class="comment">     * &#x8FD9;&#x4E2A;&#x65B9;&#x6CD5;&#x8FD4;&#x56DE; {<span class="doctag">@code</span> v}&#xFF1B;&#x5426;&#x5219;&#x5B83;&#x5C06;&#x8FD4;&#x56DE; {<span class="doctag">@code</span> null}&#x3002;&#xFF08;&#x81F3;&#x5C11;&#x5B58;&#x5728;&#x4E00;&#x4E2A;&#x8FD9;&#x6837;&#x7684;&#x6620;&#x5C04;&#x3002;&#xFF09;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * &lt;p&gt;&#x8FD4;&#x56DE;&#x503C;&#x4E3A; {<span class="doctag">@code</span> null} &#x7684;&#x60C5;&#x51B5;&#x5E76;&#x4E0D;&#x9700;&#x8981;&#x8BF4;&#x660E;&#x8FD9;&#x4E2A;map&#x4E0D;&#x5305;&#x542B;&#x8FD9;&#x4E2A;key&#xFF1B;&#x4E5F;&#x6709;&#x53EF;&#x80FD;&#x8FD9;&#x4E2A;</span></span><br><span class="line"><span class="comment">     * map&#x663E;&#x793A;&#x6307;&#x5B9A;&#x8FD9;&#x4E2A;key&#x7684;&#x503C;&#x4E3A; {<span class="doctag">@code</span> null}&#x3002;{<span class="doctag">@link</span> #containsKey containsKey} </span></span><br><span class="line"><span class="comment">     * &#x65B9;&#x6CD5;&#x5C31;&#x662F;&#x7528;&#x6765;&#x533A;&#x5206;&#x8FD9;&#x4E24;&#x79CD;&#x60C5;&#x51B5;&#x3002;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> #put(Object, Object)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">get</span><span class="params">(Object key)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt; e;</span><br><span class="line">        <span class="keyword">return</span> (e = getNode(hash(key), key)) == <span class="keyword">null</span> ? <span class="keyword">null</span> : e.value;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5B9E;&#x73B0; Map.get &#x548C;&#x76F8;&#x5173;&#x65B9;&#x6CD5;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> hash key&#x7684;hash&#x503C;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key &#x6307;&#x5B9A;&#x7684;key</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> key&#x5BF9;&#x5E94;&#x7684;&#x8282;&#x70B9;&#xFF0C;&#x5982;&#x679C;&#x6CA1;&#x6709;&#x8FD4;&#x56DE; null</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">final</span> Node&lt;K,V&gt; <span class="title">getNode</span><span class="params">(<span class="keyword">int</span> hash, Object key)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt;[] tab; Node&lt;K,V&gt; first, e; <span class="keyword">int</span> n; K k;</span><br><span class="line">        <span class="keyword">if</span> ((tab = table) != <span class="keyword">null</span> &amp;&amp; (n = tab.length) &gt; <span class="number">0</span> &amp;&amp;</span><br><span class="line">            (first = tab[(n - <span class="number">1</span>) &amp; hash]) != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">if</span> (first.hash == hash &amp;&amp; <span class="comment">// &#x603B;&#x662F;&#x5148;&#x68C0;&#x67E5;&#x7B2C;&#x4E00;&#x4E2A;&#x8282;&#x70B9;</span></span><br><span class="line">                ((k = first.key) == key || (key != <span class="keyword">null</span> &amp;&amp; key.equals(k))))</span><br><span class="line">                <span class="keyword">return</span> first;</span><br><span class="line">            <span class="keyword">if</span> ((e = first.next) != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">if</span> (first <span class="keyword">instanceof</span> TreeNode)</span><br><span class="line">                    <span class="keyword">return</span> ((TreeNode&lt;K,V&gt;)first).getTreeNode(hash, key);</span><br><span class="line">                <span class="keyword">do</span> {</span><br><span class="line">                    <span class="keyword">if</span> (e.hash == hash &amp;&amp;</span><br><span class="line">                        ((k = e.key) == key || (key != <span class="keyword">null</span> &amp;&amp; key.equals(k))))</span><br><span class="line">                        <span class="keyword">return</span> e;</span><br><span class="line">                } <span class="keyword">while</span> ((e = e.next) != <span class="keyword">null</span>);</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**=</span></span><br><span class="line"><span class="comment">     * &#x5982;&#x679C;&#x8FD9;&#x4E2A;map&#x5305;&#x542B;&#x4E86;&#x6307;&#x5B9A;key&#x7684;&#x6620;&#x5C04;&#x5173;&#x7CFB;&#xFF0C;&#x5219;&#x8FD4;&#x56DE; &lt;tt&gt;true&lt;/tt&gt;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span>   key   &#x9700;&#x8981;&#x88AB;&#x68C0;&#x6D4B;&#x5B58;&#x5728;&#x6027;&#x7684;&#x6307;&#x5B9A;key</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#x5982;&#x679C;&#x8FD9;&#x4E2A;map&#x5305;&#x542B;&#x6307;&#x5B9A;key&#x7684;&#x6620;&#x5C04;&#x5173;&#x7CFB;&#xFF0C;&#x5219;&#x8FD4;&#x56DE; &lt;tt&gt;true&lt;/tt&gt;&#x3002;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">containsKey</span><span class="params">(Object key)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> getNode(hash(key), key) != <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5728;&#x8FD9;&#x4E2A;map&#x4E2D;&#xFF0C;&#x6307;&#x5B9A;key&#x5173;&#x8054;&#x6307;&#x5B9A;&#x503C;&#x3002;&#x5982;&#x679C;&#x8FD9;&#x4E2A;map&#x4E4B;&#x524D;&#x5305;&#x542B;&#x4E86;&#x8FD9;&#x4E2A;key&#x7684;&#x6620;&#x5C04;&#x5173;&#x7CFB;&#xFF0C;&#x8001;&#x7684;&#x503C;&#x5C06;&#x4F1A;&#x88AB;&#x66FF;&#x6362;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key &#x5C06;&#x548C;&#x6307;&#x5B9A;value&#x6620;&#x5C04;&#x7684;key</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value &#x5C06;&#x548C;&#x6307;&#x5B9A;key&#x6620;&#x5C04;&#x7684;value</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &lt;tt&gt;key&lt;/tt&gt; &#x6620;&#x5C04;&#x7684;&#x4E4B;&#x524D;&#x7684;&#x503C;, &#x6216;&#x8005;&#x5982;&#x679C;&#x4E4B;&#x524D;&#x6CA1;&#x6709;&#x5BF9;&#x5E94; &lt;tt&gt;key&lt;/tt&gt;</span></span><br><span class="line"><span class="comment">     *         &#x7684;&#x6620;&#x5C04;&#x5173;&#x7CFB;&#x8FD4;&#x56DE;&#xFF0C;&lt;tt&gt;null&lt;/tt&gt;&#x3002;&#xFF08;&#x4E00;&#x4E2A; &lt;tt&gt;null&lt;/tt&gt; &#x8FD4;&#x56DE;&#x4E5F;&#x53EF;&#x4EE5;&#x7528;&#x6765;&#x8BC1;&#x660E;&#x4E4B;&#x524D;</span></span><br><span class="line"><span class="comment">     *         &#x7684;key&#x662F;&#x5426;&#x6709;&#x8FC7;&#x6620;&#x5C04;&#x5173;&#x7CFB;&#xFF09;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">put</span><span class="params">(K key, V value)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> putVal(hash(key), key, value, <span class="keyword">false</span>, <span class="keyword">true</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5B9E;&#x73B0; Map.put &#x548C;&#x5173;&#x8054;&#x65B9;&#x6CD5;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> hash key&#x7684;hash&#x503C;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key &#x6307;&#x5B9A;key</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value &#x9700;&#x8981;&#x653E;&#x5165;&#x7684;&#x503C;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> onlyIfAbsent &#x5982;&#x679C;&#x4E3A;&#x771F;&#xFF0C;&#x5219;&#x4E0D;&#x4F1A;&#x8986;&#x76D6;&#x4E4B;&#x524D;&#x7684;&#x503C;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> evict &#x5982;&#x679C;&#x4E3A;false&#xFF0C;&#x5219;&#x5904;&#x4E8E;&#x521B;&#x5EFA;&#x521B;&#x5EFA;&#x4E2D;&#x7684;&#x6A21;&#x5F0F;&#xFF08;&#x521D;&#x59CB;&#x5316;&#x72B6;&#x6001;&#xFF09;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#x4E4B;&#x524D;&#x7684;&#x503C;&#xFF0C;&#x5982;&#x679C;&#x4E0D;&#x5B58;&#x5728;&#x5219;&#x8FD4;&#x56DE; null</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">final</span> V <span class="title">putVal</span><span class="params">(<span class="keyword">int</span> hash, K key, V value, <span class="keyword">boolean</span> onlyIfAbsent,</span></span></span><br><span class="line"><span class="function"><span class="params">                   <span class="keyword">boolean</span> evict)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt;[] tab; Node&lt;K,V&gt; p; <span class="keyword">int</span> n, i;</span><br><span class="line">        <span class="keyword">if</span> ((tab = table) == <span class="keyword">null</span> || (n = tab.length) == <span class="number">0</span>)</span><br><span class="line">            n = (tab = resize()).length;</span><br><span class="line">        <span class="keyword">if</span> ((p = tab[i = (n - <span class="number">1</span>) &amp; hash]) == <span class="keyword">null</span>)</span><br><span class="line">            tab[i] = newNode(hash, key, value, <span class="keyword">null</span>);</span><br><span class="line">        <span class="keyword">else</span> {</span><br><span class="line">            Node&lt;K,V&gt; e; K k;</span><br><span class="line">            <span class="keyword">if</span> (p.hash == hash &amp;&amp;</span><br><span class="line">                ((k = p.key) == key || (key != <span class="keyword">null</span> &amp;&amp; key.equals(k))))</span><br><span class="line">                e = p;</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> (p <span class="keyword">instanceof</span> TreeNode)</span><br><span class="line">                e = ((TreeNode&lt;K,V&gt;)p).putTreeVal(<span class="keyword">this</span>, tab, hash, key, value);</span><br><span class="line">            <span class="keyword">else</span> {</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> binCount = <span class="number">0</span>; ; ++binCount) {</span><br><span class="line">                    <span class="keyword">if</span> ((e = p.next) == <span class="keyword">null</span>) {</span><br><span class="line">                        p.next = newNode(hash, key, value, <span class="keyword">null</span>);</span><br><span class="line">                        <span class="keyword">if</span> (binCount &gt;= TREEIFY_THRESHOLD - <span class="number">1</span>) <span class="comment">// -1 for 1st</span></span><br><span class="line">                            treeifyBin(tab, hash);</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    }</span><br><span class="line">                    <span class="keyword">if</span> (e.hash == hash &amp;&amp;</span><br><span class="line">                        ((k = e.key) == key || (key != <span class="keyword">null</span> &amp;&amp; key.equals(k))))</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    p = e;</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">if</span> (e != <span class="keyword">null</span>) { <span class="comment">// key&#x5DF2;&#x7ECF;&#x5B58;&#x5728;&#x7684;&#x6620;&#x5C04;</span></span><br><span class="line">                V oldValue = e.value;</span><br><span class="line">                <span class="keyword">if</span> (!onlyIfAbsent || oldValue == <span class="keyword">null</span>)</span><br><span class="line">                    e.value = value;</span><br><span class="line">                afterNodeAccess(e);</span><br><span class="line">                <span class="keyword">return</span> oldValue;</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        ++modCount;</span><br><span class="line">        <span class="keyword">if</span> (++size &gt; threshold)</span><br><span class="line">            resize();</span><br><span class="line">        afterNodeInsertion(evict);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x521D;&#x59CB;&#x5316;&#x6216;&#x8005;&#x500D;&#x589E;table&#x7684;&#x5927;&#x5C0F;&#x3002;&#x5982;&#x679C;&#x4E3A;null&#xFF0C;&#x5219;&#x6839;&#x636E;&#x9608;&#x503C;&#x5C5E;&#x6027;&#x91CC;&#x4FDD;&#x5B58;&#x7684;&#x521D;&#x59CB;&#x5316;&#x5BB9;&#x91CF;&#x7684;</span></span><br><span class="line"><span class="comment">     * &#x503C;&#x5206;&#x914D;&#x3002;&#x5426;&#x5219;&#xFF0C;&#x56E0;&#x4E3A;&#x6211;&#x4EEC;&#x4F7F;&#x7528;&#x7684;&#x662F;2&#x6B21;&#x65B9;&#x6269;&#x5C55;&#xFF0C;&#x6240;&#x4EE5;&#x6BCF;&#x4E2A;&#x6876;&#x8981;&#x4E48;&#x5446;&#x5728;&#x76F8;&#x540C;&#x7684;&#x7D22;&#x5F15;&#x4F4D;&#x7F6E;&#xFF0C;</span></span><br><span class="line"><span class="comment">     * &#x8981;&#x4E48;&#x4EE5;2&#x6B21;&#x65B9;&#x7684;&#x504F;&#x79FB;&#x91CF;&#x79FB;&#x52A8;&#x5230;&#x65B0;&#x7684;table&#x3002;</span></span><br><span class="line"><span class="comment">     * </span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> the table</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">final</span> Node&lt;K,V&gt;[] resize() {</span><br><span class="line">        Node&lt;K,V&gt;[] oldTab = table;</span><br><span class="line">        <span class="keyword">int</span> oldCap = (oldTab == <span class="keyword">null</span>) ? <span class="number">0</span> : oldTab.length;</span><br><span class="line">        <span class="keyword">int</span> oldThr = threshold;</span><br><span class="line">        <span class="keyword">int</span> newCap, newThr = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">if</span> (oldCap &gt; <span class="number">0</span>) {</span><br><span class="line">            <span class="keyword">if</span> (oldCap &gt;= MAXIMUM_CAPACITY) {</span><br><span class="line">                threshold = Integer.MAX_VALUE;</span><br><span class="line">                <span class="keyword">return</span> oldTab;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> ((newCap = oldCap &lt;&lt; <span class="number">1</span>) &lt; MAXIMUM_CAPACITY &amp;&amp;</span><br><span class="line">                     oldCap &gt;= DEFAULT_INITIAL_CAPACITY)</span><br><span class="line">                newThr = oldThr &lt;&lt; <span class="number">1</span>; <span class="comment">// &#x9608;&#x503C;&#x52A0;&#x500D;</span></span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (oldThr &gt; <span class="number">0</span>) <span class="comment">// &#x7528;&#x9608;&#x503C;&#x6765;&#x521D;&#x59CB;&#x5316;&#x521D;&#x59CB;&#x5BB9;&#x91CF;</span></span><br><span class="line">            newCap = oldThr;</span><br><span class="line">        <span class="keyword">else</span> {               <span class="comment">// &#x9608;&#x503C;&#x4E3A;0&#xFF0C;&#x5219;&#x4F7F;&#x7528;&#x9ED8;&#x8BA4;&#x503C;&#x521D;&#x59CB;&#x5316;&#x5BB9;&#x91CF;&#x4EE5;&#x53CA;&#x9608;&#x503C;</span></span><br><span class="line">            newCap = DEFAULT_INITIAL_CAPACITY;</span><br><span class="line">            newThr = (<span class="keyword">int</span>)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">if</span> (newThr == <span class="number">0</span>) {</span><br><span class="line">            <span class="keyword">float</span> ft = (<span class="keyword">float</span>)newCap * loadFactor;</span><br><span class="line">            newThr = (newCap &lt; MAXIMUM_CAPACITY &amp;&amp; ft &lt; (<span class="keyword">float</span>)MAXIMUM_CAPACITY ?</span><br><span class="line">                      (<span class="keyword">int</span>)ft : Integer.MAX_VALUE);</span><br><span class="line">        }</span><br><span class="line">        threshold = newThr;</span><br><span class="line">        <span class="meta">@SuppressWarnings</span>({<span class="string">&quot;rawtypes&quot;</span>,<span class="string">&quot;unchecked&quot;</span>})</span><br><span class="line">            Node&lt;K,V&gt;[] newTab = (Node&lt;K,V&gt;[])<span class="keyword">new</span> Node[newCap];</span><br><span class="line">        table = newTab;</span><br><span class="line">        <span class="keyword">if</span> (oldTab != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; oldCap; ++j) {</span><br><span class="line">                Node&lt;K,V&gt; e;</span><br><span class="line">                <span class="keyword">if</span> ((e = oldTab[j]) != <span class="keyword">null</span>) {</span><br><span class="line">                    oldTab[j] = <span class="keyword">null</span>;</span><br><span class="line">                    <span class="keyword">if</span> (e.next == <span class="keyword">null</span>)</span><br><span class="line">                        newTab[e.hash &amp; (newCap - <span class="number">1</span>)] = e;</span><br><span class="line">                    <span class="keyword">else</span> <span class="keyword">if</span> (e <span class="keyword">instanceof</span> TreeNode)</span><br><span class="line">                        ((TreeNode&lt;K,V&gt;)e).split(<span class="keyword">this</span>, newTab, j, oldCap);</span><br><span class="line">                    <span class="keyword">else</span> { <span class="comment">// &#x4FDD;&#x8BC1;&#x987A;&#x5E8F;</span></span><br><span class="line">                        Node&lt;K,V&gt; loHead = <span class="keyword">null</span>, loTail = <span class="keyword">null</span>;</span><br><span class="line">                        Node&lt;K,V&gt; hiHead = <span class="keyword">null</span>, hiTail = <span class="keyword">null</span>;</span><br><span class="line">                        Node&lt;K,V&gt; next;</span><br><span class="line">                        <span class="keyword">do</span> {</span><br><span class="line">                            next = e.next;</span><br><span class="line">                            <span class="keyword">if</span> ((e.hash &amp; oldCap) == <span class="number">0</span>) {</span><br><span class="line">                                <span class="keyword">if</span> (loTail == <span class="keyword">null</span>)</span><br><span class="line">                                    loHead = e;</span><br><span class="line">                                <span class="keyword">else</span></span><br><span class="line">                                    loTail.next = e;</span><br><span class="line">                                loTail = e;</span><br><span class="line">                            }</span><br><span class="line">                            <span class="keyword">else</span> {</span><br><span class="line">                                <span class="keyword">if</span> (hiTail == <span class="keyword">null</span>)</span><br><span class="line">                                    hiHead = e;</span><br><span class="line">                                <span class="keyword">else</span></span><br><span class="line">                                    hiTail.next = e;</span><br><span class="line">                                hiTail = e;</span><br><span class="line">                            }</span><br><span class="line">                        } <span class="keyword">while</span> ((e = next) != <span class="keyword">null</span>);</span><br><span class="line">                        <span class="keyword">if</span> (loTail != <span class="keyword">null</span>) {</span><br><span class="line">                            loTail.next = <span class="keyword">null</span>;</span><br><span class="line">                            newTab[j] = loHead;</span><br><span class="line">                        }</span><br><span class="line">                        <span class="keyword">if</span> (hiTail != <span class="keyword">null</span>) {</span><br><span class="line">                            hiTail.next = <span class="keyword">null</span>;</span><br><span class="line">                            newTab[j + oldCap] = hiHead;</span><br><span class="line">                        }</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> newTab;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x66FF;&#x6362;&#x6839;&#x636E;&#x6307;&#x5B9A;hash&#x6240;&#x5728;&#x7684;&#x7D22;&#x5F15;&#x4F4D;&#x7F6E;&#x4E0A;&#x7684;&#x6876;&#x5143;&#x7D20;&#xFF0C;&#x9664;&#x975E;table&#x592A;&#x5C0F;&#xFF0C;&#x4EE5;&#x6269;&#x5BB9;&#x64CD;&#x4F5C;&#x66FF;&#x4EE3;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">final</span> <span class="keyword">void</span> <span class="title">treeifyBin</span><span class="params">(Node&lt;K,V&gt;[] tab, <span class="keyword">int</span> hash)</span> </span>{</span><br><span class="line">        <span class="keyword">int</span> n, index; Node&lt;K,V&gt; e;</span><br><span class="line">        <span class="keyword">if</span> (tab == <span class="keyword">null</span> || (n = tab.length) &lt; MIN_TREEIFY_CAPACITY)</span><br><span class="line">            resize();</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> ((e = tab[index = (n - <span class="number">1</span>) &amp; hash]) != <span class="keyword">null</span>) {</span><br><span class="line">            TreeNode&lt;K,V&gt; hd = <span class="keyword">null</span>, tl = <span class="keyword">null</span>;</span><br><span class="line">            <span class="keyword">do</span> {</span><br><span class="line">                TreeNode&lt;K,V&gt; p = replacementTreeNode(e, <span class="keyword">null</span>);</span><br><span class="line">                <span class="keyword">if</span> (tl == <span class="keyword">null</span>)</span><br><span class="line">                    hd = p;</span><br><span class="line">                <span class="keyword">else</span> {</span><br><span class="line">                    p.prev = tl;</span><br><span class="line">                    tl.next = p;</span><br><span class="line">                }</span><br><span class="line">                tl = p;</span><br><span class="line">            } <span class="keyword">while</span> ((e = e.next) != <span class="keyword">null</span>);</span><br><span class="line">            <span class="keyword">if</span> ((tab[index] = hd) != <span class="keyword">null</span>)</span><br><span class="line">                hd.treeify(tab);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x4ECE;&#x6307;&#x5B9A;&#x7684;map&#x5185;&#x62F7;&#x8D1D;&#x6240;&#x6709;&#x7684;&#x952E;&#x503C;&#x5BF9;&#x5230;&#x8FD9;&#x4E2A;map&#x4E2D;&#x3002;</span></span><br><span class="line"><span class="comment">     * &#x8FD9;&#x4E9B;&#x952E;&#x503C;&#x5BF9;&#x4F1A;&#x8986;&#x76D6;&#x5728;&#x6307;&#x5B9A;map&#x4E2D;&#x5DF2;&#x7ECF;&#x5B58;&#x5728;&#x7684;key&#x6240;&#x6620;&#x5C04;&#x7684;&#x6240;&#x6709;&#x952E;&#x503C;&#x5BF9;&#x3002;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> m &#x5C06;&#x88AB;&#x5B58;&#x50A8;&#x5728;&#x8FD9;&#x4E2A;map&#x7684;&#x952E;&#x503C;&#x5BF9;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> NullPointerException &#x5982;&#x679C;&#x6307;&#x5B9A;map&#x4E3A;&#x7A7A;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">putAll</span><span class="params">(Map&lt;? extends K, ? extends V&gt; m)</span> </span>{</span><br><span class="line">        putMapEntries(m, <span class="keyword">true</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5982;&#x679C;&#x8FD9;&#x4E2A;key&#x5B58;&#x5728;&#xFF0C;&#x5220;&#x9664;&#x6307;&#x5B9A;key&#x7684;&#x952E;&#x503C;&#x5BF9;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span>  key &#x5C06;&#x88AB;&#x4ECE;map&#x4E2D;&#x5220;&#x9664;&#x952E;&#x503C;&#x5BF9;&#x7684;key</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> the &#x4E4B;&#x524D;&#x6620;&#x5C04;&#x5230;&#x8FD9;&#x4E2A; &lt;tt&gt;key&lt;/tt&gt; &#x7684;&#x503C;, &#x5982;&#x679C;&#x6CA1;&#x6709;&#x6620;&#x5C04; &lt;tt&gt;key&lt;/tt&gt; &#xFF0C;</span></span><br><span class="line"><span class="comment">     * &#x5219;&#x8FD4;&#x56DE; &lt;tt&gt;null&lt;/tt&gt;&#x3002;&#xFF08;&#x5F53;map&#x4E4B;&#x524D;&#x6709;&#x5173;&#x8054;&#x8FC7; &lt;tt&gt;key&lt;/tt&gt; &#x6240;&#x6620;&#x5C04;&#x7684;&#x503C;&#x4E3A;</span></span><br><span class="line"><span class="comment">     * &lt;tt&gt;null&lt;/tt&gt; &#x7684;&#xFF0C;&#x4E5F;&#x6709;&#x53EF;&#x80FD;&#x4F1A;&#x88AB;&#x4F1A;&#x76F4;&#x63A5;&#x8FD4;&#x56DE; &lt;tt&gt;null&lt;/tt&gt;&#xFF09;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">remove</span><span class="params">(Object key)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt; e;</span><br><span class="line">        <span class="keyword">return</span> (e = removeNode(hash(key), key, <span class="keyword">null</span>, <span class="keyword">false</span>, <span class="keyword">true</span>)) == <span class="keyword">null</span> ?</span><br><span class="line">            <span class="keyword">null</span> : e.value;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5B9E;&#x73B0; Map.remove &#x548C;&#x76F8;&#x5173;&#x7684;&#x65B9;&#x6CD5;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> hash key&#x7684;hash&#x503C;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key the key</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value &#x5982;&#x679C;&#x8BBE;&#x7F6E;&#x4E86;matchValue&#x4E3A;true&#xFF0C;&#x5219;&#x9700;&#x8981;&#x5339;&#x914D;value&#xFF0C;&#x5426;&#x5219;&#x5FFD;&#x7565;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> matchValue &#x5F53;matchValue&#x4E3A;&#x771F;&#x65F6;&#xFF0C;value&#x503C;&#x76F8;&#x7B49;&#x624D;&#x4F1A;&#x5220;&#x9664;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> movable &#x5982;&#x679C;&#x4E3A;&#x5047;&#xFF0C;&#x5219;&#x4E0D;&#x8981;&#x5728;&#x79FB;&#x52A8;&#x65F6;&#x79FB;&#x52A8;&#x5176;&#x4ED6;&#x8282;&#x70B9;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#x88AB;&#x5220;&#x9664;&#x7684;&#x8282;&#x70B9;&#xFF0C;&#x5426;&#x5219;&#x8FD4;&#x56DE;null</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">final</span> Node&lt;K,V&gt; <span class="title">removeNode</span><span class="params">(<span class="keyword">int</span> hash, Object key, Object value,</span></span></span><br><span class="line"><span class="function"><span class="params">                               <span class="keyword">boolean</span> matchValue, <span class="keyword">boolean</span> movable)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt;[] tab; Node&lt;K,V&gt; p; <span class="keyword">int</span> n, index;</span><br><span class="line">        <span class="keyword">if</span> ((tab = table) != <span class="keyword">null</span> &amp;&amp; (n = tab.length) &gt; <span class="number">0</span> &amp;&amp;</span><br><span class="line">            (p = tab[index = (n - <span class="number">1</span>) &amp; hash]) != <span class="keyword">null</span>) {</span><br><span class="line">            Node&lt;K,V&gt; node = <span class="keyword">null</span>, e; K k; V v;</span><br><span class="line">            <span class="keyword">if</span> (p.hash == hash &amp;&amp;</span><br><span class="line">                ((k = p.key) == key || (key != <span class="keyword">null</span> &amp;&amp; key.equals(k))))</span><br><span class="line">                node = p;</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> ((e = p.next) != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">if</span> (p <span class="keyword">instanceof</span> TreeNode)</span><br><span class="line">                    node = ((TreeNode&lt;K,V&gt;)p).getTreeNode(hash, key);</span><br><span class="line">                <span class="keyword">else</span> {</span><br><span class="line">                    <span class="keyword">do</span> {</span><br><span class="line">                        <span class="keyword">if</span> (e.hash == hash &amp;&amp;</span><br><span class="line">                            ((k = e.key) == key ||</span><br><span class="line">                             (key != <span class="keyword">null</span> &amp;&amp; key.equals(k)))) {</span><br><span class="line">                            node = e;</span><br><span class="line">                            <span class="keyword">break</span>;</span><br><span class="line">                        }</span><br><span class="line">                        p = e;</span><br><span class="line">                    } <span class="keyword">while</span> ((e = e.next) != <span class="keyword">null</span>);</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">if</span> (node != <span class="keyword">null</span> &amp;&amp; (!matchValue || (v = node.value) == value ||</span><br><span class="line">                                 (value != <span class="keyword">null</span> &amp;&amp; value.equals(v)))) {</span><br><span class="line">                <span class="keyword">if</span> (node <span class="keyword">instanceof</span> TreeNode)</span><br><span class="line">                    ((TreeNode&lt;K,V&gt;)node).removeTreeNode(<span class="keyword">this</span>, tab, movable);</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (node == p)</span><br><span class="line">                    tab[index] = node.next;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    p.next = node.next;</span><br><span class="line">                ++modCount;</span><br><span class="line">                --size;</span><br><span class="line">                afterNodeRemoval(node);</span><br><span class="line">                <span class="keyword">return</span> node;</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5220;&#x9664;&#x6240;&#x6709;&#x7684;&#x952E;&#x503C;&#x5BF9;</span></span><br><span class="line"><span class="comment">     * &#x5728;&#x8FD9;&#x4E2A;&#x65B9;&#x6CD5;&#x6267;&#x884C;&#x8FD4;&#x56DE;&#x540E;&#xFF0C;map&#x5C06;&#x4F1A;&#x4E3A;&#x7A7A;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">clear</span><span class="params">()</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt;[] tab;</span><br><span class="line">        modCount++;</span><br><span class="line">        <span class="keyword">if</span> ((tab = table) != <span class="keyword">null</span> &amp;&amp; size &gt; <span class="number">0</span>) {</span><br><span class="line">            size = <span class="number">0</span>;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; tab.length; ++i)</span><br><span class="line">                tab[i] = <span class="keyword">null</span>;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5982;&#x679C;&#x8FD9;&#x4E2A;map&#x6620;&#x5C04;&#x7684;&#x7279;&#x5B9A;&#x503C;&#x6709;&#x4E00;&#x4E2A;&#x6216;&#x591A;&#x4E2A;key&#x5219;&#x8FD4;&#x56DE; &lt;tt&gt;true&lt;/tt&gt;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value &#x5728;&#x8FD9;&#x4E2A;map&#x4E2D;&#x5C06;&#x8981;&#x88AB;&#x6D4B;&#x8BD5;&#x662F;&#x5426;&#x5B58;&#x5728;&#x7684;&#x503C;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#x8FD4;&#x56DE; &lt;tt&gt;true&lt;/tt&gt; &#x5982;&#x679C;&#x8FD9;&#x4E2A;map&#x4E2D;&#x7684;&#x7279;&#x5B9A;&#x503C;&#x5173;&#x8054;&#x4E86;&#x4E00;&#x4E2A;&#x6216;&#x591A;&#x4E2A;key</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">containsValue</span><span class="params">(Object value)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt;[] tab; V v;</span><br><span class="line">        <span class="keyword">if</span> ((tab = table) != <span class="keyword">null</span> &amp;&amp; size &gt; <span class="number">0</span>) {</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; tab.length; ++i) {</span><br><span class="line">                <span class="keyword">for</span> (Node&lt;K,V&gt; e = tab[i]; e != <span class="keyword">null</span>; e = e.next) {</span><br><span class="line">                    <span class="keyword">if</span> ((v = e.value) == value ||</span><br><span class="line">                        (value != <span class="keyword">null</span> &amp;&amp; value.equals(v)))</span><br><span class="line">                        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * </span></span><br><span class="line"><span class="comment">     * Returns a {<span class="doctag">@link</span> Set} view of the keys contained in this map.</span></span><br><span class="line"><span class="comment">     * The set is backed by the map, so changes to the map are</span></span><br><span class="line"><span class="comment">     * reflected in the set, and vice-versa.  If the map is modified</span></span><br><span class="line"><span class="comment">     * while an iteration over the set is in progress (except through</span></span><br><span class="line"><span class="comment">     * the iterator&apos;s own &lt;tt&gt;remove&lt;/tt&gt; operation), the results of</span></span><br><span class="line"><span class="comment">     * the iteration are undefined.  The set supports element removal,</span></span><br><span class="line"><span class="comment">     * which removes the corresponding mapping from the map, via the</span></span><br><span class="line"><span class="comment">     * &lt;tt&gt;Iterator.remove&lt;/tt&gt;, &lt;tt&gt;Set.remove&lt;/tt&gt;,</span></span><br><span class="line"><span class="comment">     * &lt;tt&gt;removeAll&lt;/tt&gt;, &lt;tt&gt;retainAll&lt;/tt&gt;, and &lt;tt&gt;clear&lt;/tt&gt;</span></span><br><span class="line"><span class="comment">     * operations.  It does not support the &lt;tt&gt;add&lt;/tt&gt; or &lt;tt&gt;addAll&lt;/tt&gt;</span></span><br><span class="line"><span class="comment">     * operations.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> a set view of the keys contained in this map</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Set&lt;K&gt; <span class="title">keySet</span><span class="params">()</span> </span>{</span><br><span class="line">        Set&lt;K&gt; ks = keySet;</span><br><span class="line">        <span class="keyword">if</span> (ks == <span class="keyword">null</span>) {</span><br><span class="line">            ks = <span class="keyword">new</span> KeySet();</span><br><span class="line">            keySet = ks;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> ks;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">KeySet</span> <span class="keyword">extends</span> <span class="title">AbstractSet</span>&lt;<span class="title">K</span>&gt; </span>{</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">int</span> <span class="title">size</span><span class="params">()</span>                 </span>{ <span class="keyword">return</span> size; }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title">clear</span><span class="params">()</span>               </span>{ HashMap.<span class="keyword">this</span>.clear(); }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> Iterator&lt;K&gt; <span class="title">iterator</span><span class="params">()</span>     </span>{ <span class="keyword">return</span> <span class="keyword">new</span> KeyIterator(); }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">boolean</span> <span class="title">contains</span><span class="params">(Object o)</span> </span>{ <span class="keyword">return</span> containsKey(o); }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">boolean</span> <span class="title">remove</span><span class="params">(Object key)</span> </span>{</span><br><span class="line">            <span class="keyword">return</span> removeNode(hash(key), key, <span class="keyword">null</span>, <span class="keyword">false</span>, <span class="keyword">true</span>) != <span class="keyword">null</span>;</span><br><span class="line">        }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> Spliterator&lt;K&gt; <span class="title">spliterator</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> KeySpliterator&lt;&gt;(HashMap.<span class="keyword">this</span>, <span class="number">0</span>, -<span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">        }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title">forEach</span><span class="params">(Consumer&lt;? <span class="keyword">super</span> K&gt; action)</span> </span>{</span><br><span class="line">            Node&lt;K,V&gt;[] tab;</span><br><span class="line">            <span class="keyword">if</span> (action == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">            <span class="keyword">if</span> (size &gt; <span class="number">0</span> &amp;&amp; (tab = table) != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">int</span> mc = modCount;</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; tab.length; ++i) {</span><br><span class="line">                    <span class="keyword">for</span> (Node&lt;K,V&gt; e = tab[i]; e != <span class="keyword">null</span>; e = e.next)</span><br><span class="line">                        action.accept(e.key);</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">if</span> (modCount != mc)</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Returns a {<span class="doctag">@link</span> Collection} view of the values contained in this map.</span></span><br><span class="line"><span class="comment">     * The collection is backed by the map, so changes to the map are</span></span><br><span class="line"><span class="comment">     * reflected in the collection, and vice-versa.  If the map is</span></span><br><span class="line"><span class="comment">     * modified while an iteration over the collection is in progress</span></span><br><span class="line"><span class="comment">     * (except through the iterator&apos;s own &lt;tt&gt;remove&lt;/tt&gt; operation),</span></span><br><span class="line"><span class="comment">     * the results of the iteration are undefined.  The collection</span></span><br><span class="line"><span class="comment">     * supports element removal, which removes the corresponding</span></span><br><span class="line"><span class="comment">     * mapping from the map, via the &lt;tt&gt;Iterator.remove&lt;/tt&gt;,</span></span><br><span class="line"><span class="comment">     * &lt;tt&gt;Collection.remove&lt;/tt&gt;, &lt;tt&gt;removeAll&lt;/tt&gt;,</span></span><br><span class="line"><span class="comment">     * &lt;tt&gt;retainAll&lt;/tt&gt; and &lt;tt&gt;clear&lt;/tt&gt; operations.  It does not</span></span><br><span class="line"><span class="comment">     * support the &lt;tt&gt;add&lt;/tt&gt; or &lt;tt&gt;addAll&lt;/tt&gt; operations.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> a view of the values contained in this map</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Collection&lt;V&gt; <span class="title">values</span><span class="params">()</span> </span>{</span><br><span class="line">        Collection&lt;V&gt; vs = values;</span><br><span class="line">        <span class="keyword">if</span> (vs == <span class="keyword">null</span>) {</span><br><span class="line">            vs = <span class="keyword">new</span> Values();</span><br><span class="line">            values = vs;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> vs;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">Values</span> <span class="keyword">extends</span> <span class="title">AbstractCollection</span>&lt;<span class="title">V</span>&gt; </span>{</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">int</span> <span class="title">size</span><span class="params">()</span>                 </span>{ <span class="keyword">return</span> size; }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title">clear</span><span class="params">()</span>               </span>{ HashMap.<span class="keyword">this</span>.clear(); }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> Iterator&lt;V&gt; <span class="title">iterator</span><span class="params">()</span>     </span>{ <span class="keyword">return</span> <span class="keyword">new</span> ValueIterator(); }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">boolean</span> <span class="title">contains</span><span class="params">(Object o)</span> </span>{ <span class="keyword">return</span> containsValue(o); }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> Spliterator&lt;V&gt; <span class="title">spliterator</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> ValueSpliterator&lt;&gt;(HashMap.<span class="keyword">this</span>, <span class="number">0</span>, -<span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">        }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title">forEach</span><span class="params">(Consumer&lt;? <span class="keyword">super</span> V&gt; action)</span> </span>{</span><br><span class="line">            Node&lt;K,V&gt;[] tab;</span><br><span class="line">            <span class="keyword">if</span> (action == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">            <span class="keyword">if</span> (size &gt; <span class="number">0</span> &amp;&amp; (tab = table) != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">int</span> mc = modCount;</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; tab.length; ++i) {</span><br><span class="line">                    <span class="keyword">for</span> (Node&lt;K,V&gt; e = tab[i]; e != <span class="keyword">null</span>; e = e.next)</span><br><span class="line">                        action.accept(e.value);</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">if</span> (modCount != mc)</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Returns a {<span class="doctag">@link</span> Set} view of the mappings contained in this map.</span></span><br><span class="line"><span class="comment">     * The set is backed by the map, so changes to the map are</span></span><br><span class="line"><span class="comment">     * reflected in the set, and vice-versa.  If the map is modified</span></span><br><span class="line"><span class="comment">     * while an iteration over the set is in progress (except through</span></span><br><span class="line"><span class="comment">     * the iterator&apos;s own &lt;tt&gt;remove&lt;/tt&gt; operation, or through the</span></span><br><span class="line"><span class="comment">     * &lt;tt&gt;setValue&lt;/tt&gt; operation on a map entry returned by the</span></span><br><span class="line"><span class="comment">     * iterator) the results of the iteration are undefined.  The set</span></span><br><span class="line"><span class="comment">     * supports element removal, which removes the corresponding</span></span><br><span class="line"><span class="comment">     * mapping from the map, via the &lt;tt&gt;Iterator.remove&lt;/tt&gt;,</span></span><br><span class="line"><span class="comment">     * &lt;tt&gt;Set.remove&lt;/tt&gt;, &lt;tt&gt;removeAll&lt;/tt&gt;, &lt;tt&gt;retainAll&lt;/tt&gt; and</span></span><br><span class="line"><span class="comment">     * &lt;tt&gt;clear&lt;/tt&gt; operations.  It does not support the</span></span><br><span class="line"><span class="comment">     * &lt;tt&gt;add&lt;/tt&gt; or &lt;tt&gt;addAll&lt;/tt&gt; operations.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> a set view of the mappings contained in this map</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> Set&lt;Map.Entry&lt;K,V&gt;&gt; entrySet() {</span><br><span class="line">        Set&lt;Map.Entry&lt;K,V&gt;&gt; es;</span><br><span class="line">        <span class="keyword">return</span> (es = entrySet) == <span class="keyword">null</span> ? (entrySet = <span class="keyword">new</span> EntrySet()) : es;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">EntrySet</span> <span class="keyword">extends</span> <span class="title">AbstractSet</span>&lt;<span class="title">Map</span>.<span class="title">Entry</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;&gt; </span>{</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">int</span> <span class="title">size</span><span class="params">()</span>                 </span>{ <span class="keyword">return</span> size; }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title">clear</span><span class="params">()</span>               </span>{ HashMap.<span class="keyword">this</span>.clear(); }</span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">final</span> Iterator&lt;Map.Entry&lt;K,V&gt;&gt; iterator() {</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> EntryIterator();</span><br><span class="line">        }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">boolean</span> <span class="title">contains</span><span class="params">(Object o)</span> </span>{</span><br><span class="line">            <span class="keyword">if</span> (!(o <span class="keyword">instanceof</span> Map.Entry))</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            Map.Entry&lt;?,?&gt; e = (Map.Entry&lt;?,?&gt;) o;</span><br><span class="line">            Object key = e.getKey();</span><br><span class="line">            Node&lt;K,V&gt; candidate = getNode(hash(key), key);</span><br><span class="line">            <span class="keyword">return</span> candidate != <span class="keyword">null</span> &amp;&amp; candidate.equals(e);</span><br><span class="line">        }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">boolean</span> <span class="title">remove</span><span class="params">(Object o)</span> </span>{</span><br><span class="line">            <span class="keyword">if</span> (o <span class="keyword">instanceof</span> Map.Entry) {</span><br><span class="line">                Map.Entry&lt;?,?&gt; e = (Map.Entry&lt;?,?&gt;) o;</span><br><span class="line">                Object key = e.getKey();</span><br><span class="line">                Object value = e.getValue();</span><br><span class="line">                <span class="keyword">return</span> removeNode(hash(key), key, value, <span class="keyword">true</span>, <span class="keyword">true</span>) != <span class="keyword">null</span>;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">final</span> Spliterator&lt;Map.Entry&lt;K,V&gt;&gt; spliterator() {</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> EntrySpliterator&lt;&gt;(HashMap.<span class="keyword">this</span>, <span class="number">0</span>, -<span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">        }</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title">forEach</span><span class="params">(Consumer&lt;? <span class="keyword">super</span> Map.Entry&lt;K,V&gt;&gt; action)</span> </span>{</span><br><span class="line">            Node&lt;K,V&gt;[] tab;</span><br><span class="line">            <span class="keyword">if</span> (action == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">            <span class="keyword">if</span> (size &gt; <span class="number">0</span> &amp;&amp; (tab = table) != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">int</span> mc = modCount;</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; tab.length; ++i) {</span><br><span class="line">                    <span class="keyword">for</span> (Node&lt;K,V&gt; e = tab[i]; e != <span class="keyword">null</span>; e = e.next)</span><br><span class="line">                        action.accept(e);</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">if</span> (modCount != mc)</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Overrides of JDK8 Map extension methods</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">getOrDefault</span><span class="params">(Object key, V defaultValue)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt; e;</span><br><span class="line">        <span class="keyword">return</span> (e = getNode(hash(key), key)) == <span class="keyword">null</span> ? defaultValue : e.value;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">putIfAbsent</span><span class="params">(K key, V value)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> putVal(hash(key), key, value, <span class="keyword">true</span>, <span class="keyword">true</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">remove</span><span class="params">(Object key, Object value)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> removeNode(hash(key), key, value, <span class="keyword">true</span>, <span class="keyword">true</span>) != <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">replace</span><span class="params">(K key, V oldValue, V newValue)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt; e; V v;</span><br><span class="line">        <span class="keyword">if</span> ((e = getNode(hash(key), key)) != <span class="keyword">null</span> &amp;&amp;</span><br><span class="line">            ((v = e.value) == oldValue || (v != <span class="keyword">null</span> &amp;&amp; v.equals(oldValue)))) {</span><br><span class="line">            e.value = newValue;</span><br><span class="line">            afterNodeAccess(e);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">replace</span><span class="params">(K key, V value)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt; e;</span><br><span class="line">        <span class="keyword">if</span> ((e = getNode(hash(key), key)) != <span class="keyword">null</span>) {</span><br><span class="line">            V oldValue = e.value;</span><br><span class="line">            e.value = value;</span><br><span class="line">            afterNodeAccess(e);</span><br><span class="line">            <span class="keyword">return</span> oldValue;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">computeIfAbsent</span><span class="params">(K key,</span></span></span><br><span class="line"><span class="function"><span class="params">                             Function&lt;? <span class="keyword">super</span> K, ? extends V&gt; mappingFunction)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (mappingFunction == <span class="keyword">null</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">        <span class="keyword">int</span> hash = hash(key);</span><br><span class="line">        Node&lt;K,V&gt;[] tab; Node&lt;K,V&gt; first; <span class="keyword">int</span> n, i;</span><br><span class="line">        <span class="keyword">int</span> binCount = <span class="number">0</span>;</span><br><span class="line">        TreeNode&lt;K,V&gt; t = <span class="keyword">null</span>;</span><br><span class="line">        Node&lt;K,V&gt; old = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (size &gt; threshold || (tab = table) == <span class="keyword">null</span> ||</span><br><span class="line">            (n = tab.length) == <span class="number">0</span>)</span><br><span class="line">            n = (tab = resize()).length;</span><br><span class="line">        <span class="keyword">if</span> ((first = tab[i = (n - <span class="number">1</span>) &amp; hash]) != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">if</span> (first <span class="keyword">instanceof</span> TreeNode)</span><br><span class="line">                old = (t = (TreeNode&lt;K,V&gt;)first).getTreeNode(hash, key);</span><br><span class="line">            <span class="keyword">else</span> {</span><br><span class="line">                Node&lt;K,V&gt; e = first; K k;</span><br><span class="line">                <span class="keyword">do</span> {</span><br><span class="line">                    <span class="keyword">if</span> (e.hash == hash &amp;&amp;</span><br><span class="line">                        ((k = e.key) == key || (key != <span class="keyword">null</span> &amp;&amp; key.equals(k)))) {</span><br><span class="line">                        old = e;</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    }</span><br><span class="line">                    ++binCount;</span><br><span class="line">                } <span class="keyword">while</span> ((e = e.next) != <span class="keyword">null</span>);</span><br><span class="line">            }</span><br><span class="line">            V oldValue;</span><br><span class="line">            <span class="keyword">if</span> (old != <span class="keyword">null</span> &amp;&amp; (oldValue = old.value) != <span class="keyword">null</span>) {</span><br><span class="line">                afterNodeAccess(old);</span><br><span class="line">                <span class="keyword">return</span> oldValue;</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        V v = mappingFunction.apply(key);</span><br><span class="line">        <span class="keyword">if</span> (v == <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        } <span class="keyword">else</span> <span class="keyword">if</span> (old != <span class="keyword">null</span>) {</span><br><span class="line">            old.value = v;</span><br><span class="line">            afterNodeAccess(old);</span><br><span class="line">            <span class="keyword">return</span> v;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (t != <span class="keyword">null</span>)</span><br><span class="line">            t.putTreeVal(<span class="keyword">this</span>, tab, hash, key, v);</span><br><span class="line">        <span class="keyword">else</span> {</span><br><span class="line">            tab[i] = newNode(hash, key, v, first);</span><br><span class="line">            <span class="keyword">if</span> (binCount &gt;= TREEIFY_THRESHOLD - <span class="number">1</span>)</span><br><span class="line">                treeifyBin(tab, hash);</span><br><span class="line">        }</span><br><span class="line">        ++modCount;</span><br><span class="line">        ++size;</span><br><span class="line">        afterNodeInsertion(<span class="keyword">true</span>);</span><br><span class="line">        <span class="keyword">return</span> v;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">computeIfPresent</span><span class="params">(K key,</span></span></span><br><span class="line"><span class="function"><span class="params">                              BiFunction&lt;? <span class="keyword">super</span> K, ? <span class="keyword">super</span> V, ? extends V&gt; remappingFunction)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (remappingFunction == <span class="keyword">null</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">        Node&lt;K,V&gt; e; V oldValue;</span><br><span class="line">        <span class="keyword">int</span> hash = hash(key);</span><br><span class="line">        <span class="keyword">if</span> ((e = getNode(hash, key)) != <span class="keyword">null</span> &amp;&amp;</span><br><span class="line">            (oldValue = e.value) != <span class="keyword">null</span>) {</span><br><span class="line">            V v = remappingFunction.apply(key, oldValue);</span><br><span class="line">            <span class="keyword">if</span> (v != <span class="keyword">null</span>) {</span><br><span class="line">                e.value = v;</span><br><span class="line">                afterNodeAccess(e);</span><br><span class="line">                <span class="keyword">return</span> v;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                removeNode(hash, key, <span class="keyword">null</span>, <span class="keyword">false</span>, <span class="keyword">true</span>);</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">compute</span><span class="params">(K key,</span></span></span><br><span class="line"><span class="function"><span class="params">                     BiFunction&lt;? <span class="keyword">super</span> K, ? <span class="keyword">super</span> V, ? extends V&gt; remappingFunction)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (remappingFunction == <span class="keyword">null</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">        <span class="keyword">int</span> hash = hash(key);</span><br><span class="line">        Node&lt;K,V&gt;[] tab; Node&lt;K,V&gt; first; <span class="keyword">int</span> n, i;</span><br><span class="line">        <span class="keyword">int</span> binCount = <span class="number">0</span>;</span><br><span class="line">        TreeNode&lt;K,V&gt; t = <span class="keyword">null</span>;</span><br><span class="line">        Node&lt;K,V&gt; old = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (size &gt; threshold || (tab = table) == <span class="keyword">null</span> ||</span><br><span class="line">            (n = tab.length) == <span class="number">0</span>)</span><br><span class="line">            n = (tab = resize()).length;</span><br><span class="line">        <span class="keyword">if</span> ((first = tab[i = (n - <span class="number">1</span>) &amp; hash]) != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">if</span> (first <span class="keyword">instanceof</span> TreeNode)</span><br><span class="line">                old = (t = (TreeNode&lt;K,V&gt;)first).getTreeNode(hash, key);</span><br><span class="line">            <span class="keyword">else</span> {</span><br><span class="line">                Node&lt;K,V&gt; e = first; K k;</span><br><span class="line">                <span class="keyword">do</span> {</span><br><span class="line">                    <span class="keyword">if</span> (e.hash == hash &amp;&amp;</span><br><span class="line">                        ((k = e.key) == key || (key != <span class="keyword">null</span> &amp;&amp; key.equals(k)))) {</span><br><span class="line">                        old = e;</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    }</span><br><span class="line">                    ++binCount;</span><br><span class="line">                } <span class="keyword">while</span> ((e = e.next) != <span class="keyword">null</span>);</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        V oldValue = (old == <span class="keyword">null</span>) ? <span class="keyword">null</span> : old.value;</span><br><span class="line">        V v = remappingFunction.apply(key, oldValue);</span><br><span class="line">        <span class="keyword">if</span> (old != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">if</span> (v != <span class="keyword">null</span>) {</span><br><span class="line">                old.value = v;</span><br><span class="line">                afterNodeAccess(old);</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                removeNode(hash, key, <span class="keyword">null</span>, <span class="keyword">false</span>, <span class="keyword">true</span>);</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (v != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">if</span> (t != <span class="keyword">null</span>)</span><br><span class="line">                t.putTreeVal(<span class="keyword">this</span>, tab, hash, key, v);</span><br><span class="line">            <span class="keyword">else</span> {</span><br><span class="line">                tab[i] = newNode(hash, key, v, first);</span><br><span class="line">                <span class="keyword">if</span> (binCount &gt;= TREEIFY_THRESHOLD - <span class="number">1</span>)</span><br><span class="line">                    treeifyBin(tab, hash);</span><br><span class="line">            }</span><br><span class="line">            ++modCount;</span><br><span class="line">            ++size;</span><br><span class="line">            afterNodeInsertion(<span class="keyword">true</span>);</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> v;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">merge</span><span class="params">(K key, V value,</span></span></span><br><span class="line"><span class="function"><span class="params">                   BiFunction&lt;? <span class="keyword">super</span> V, ? <span class="keyword">super</span> V, ? extends V&gt; remappingFunction)</span> </span>{</span><br><span class="line">        <span class="keyword">if</span> (value == <span class="keyword">null</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">        <span class="keyword">if</span> (remappingFunction == <span class="keyword">null</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">        <span class="keyword">int</span> hash = hash(key);</span><br><span class="line">        Node&lt;K,V&gt;[] tab; Node&lt;K,V&gt; first; <span class="keyword">int</span> n, i;</span><br><span class="line">        <span class="keyword">int</span> binCount = <span class="number">0</span>;</span><br><span class="line">        TreeNode&lt;K,V&gt; t = <span class="keyword">null</span>;</span><br><span class="line">        Node&lt;K,V&gt; old = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (size &gt; threshold || (tab = table) == <span class="keyword">null</span> ||</span><br><span class="line">            (n = tab.length) == <span class="number">0</span>)</span><br><span class="line">            n = (tab = resize()).length;</span><br><span class="line">        <span class="keyword">if</span> ((first = tab[i = (n - <span class="number">1</span>) &amp; hash]) != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">if</span> (first <span class="keyword">instanceof</span> TreeNode)</span><br><span class="line">                old = (t = (TreeNode&lt;K,V&gt;)first).getTreeNode(hash, key);</span><br><span class="line">            <span class="keyword">else</span> {</span><br><span class="line">                Node&lt;K,V&gt; e = first; K k;</span><br><span class="line">                <span class="keyword">do</span> {</span><br><span class="line">                    <span class="keyword">if</span> (e.hash == hash &amp;&amp;</span><br><span class="line">                        ((k = e.key) == key || (key != <span class="keyword">null</span> &amp;&amp; key.equals(k)))) {</span><br><span class="line">                        old = e;</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    }</span><br><span class="line">                    ++binCount;</span><br><span class="line">                } <span class="keyword">while</span> ((e = e.next) != <span class="keyword">null</span>);</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">if</span> (old != <span class="keyword">null</span>) {</span><br><span class="line">            V v;</span><br><span class="line">            <span class="keyword">if</span> (old.value != <span class="keyword">null</span>)</span><br><span class="line">                v = remappingFunction.apply(old.value, value);</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                v = value;</span><br><span class="line">            <span class="keyword">if</span> (v != <span class="keyword">null</span>) {</span><br><span class="line">                old.value = v;</span><br><span class="line">                afterNodeAccess(old);</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                removeNode(hash, key, <span class="keyword">null</span>, <span class="keyword">false</span>, <span class="keyword">true</span>);</span><br><span class="line">            <span class="keyword">return</span> v;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">if</span> (value != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">if</span> (t != <span class="keyword">null</span>)</span><br><span class="line">                t.putTreeVal(<span class="keyword">this</span>, tab, hash, key, value);</span><br><span class="line">            <span class="keyword">else</span> {</span><br><span class="line">                tab[i] = newNode(hash, key, value, first);</span><br><span class="line">                <span class="keyword">if</span> (binCount &gt;= TREEIFY_THRESHOLD - <span class="number">1</span>)</span><br><span class="line">                    treeifyBin(tab, hash);</span><br><span class="line">            }</span><br><span class="line">            ++modCount;</span><br><span class="line">            ++size;</span><br><span class="line">            afterNodeInsertion(<span class="keyword">true</span>);</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">return</span> value;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">forEach</span><span class="params">(BiConsumer&lt;? <span class="keyword">super</span> K, ? <span class="keyword">super</span> V&gt; action)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt;[] tab;</span><br><span class="line">        <span class="keyword">if</span> (action == <span class="keyword">null</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">        <span class="keyword">if</span> (size &gt; <span class="number">0</span> &amp;&amp; (tab = table) != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">int</span> mc = modCount;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; tab.length; ++i) {</span><br><span class="line">                <span class="keyword">for</span> (Node&lt;K,V&gt; e = tab[i]; e != <span class="keyword">null</span>; e = e.next)</span><br><span class="line">                    action.accept(e.key, e.value);</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">if</span> (modCount != mc)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">replaceAll</span><span class="params">(BiFunction&lt;? <span class="keyword">super</span> K, ? <span class="keyword">super</span> V, ? extends V&gt; function)</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt;[] tab;</span><br><span class="line">        <span class="keyword">if</span> (function == <span class="keyword">null</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">        <span class="keyword">if</span> (size &gt; <span class="number">0</span> &amp;&amp; (tab = table) != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">int</span> mc = modCount;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; tab.length; ++i) {</span><br><span class="line">                <span class="keyword">for</span> (Node&lt;K,V&gt; e = tab[i]; e != <span class="keyword">null</span>; e = e.next) {</span><br><span class="line">                    e.value = function.apply(e.key, e.value);</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">if</span> (modCount != mc)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ------------------------------------------------------------ */</span></span><br><span class="line">    <span class="comment">// Cloning and serialization</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Returns a shallow copy of this &lt;tt&gt;HashMap&lt;/tt&gt; instance: the keys and</span></span><br><span class="line"><span class="comment">     * values themselves are not cloned.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> a shallow copy of this map</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@SuppressWarnings</span>(<span class="string">&quot;unchecked&quot;</span>)</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Object <span class="title">clone</span><span class="params">()</span> </span>{</span><br><span class="line">        HashMap&lt;K,V&gt; result;</span><br><span class="line">        <span class="keyword">try</span> {</span><br><span class="line">            result = (HashMap&lt;K,V&gt;)<span class="keyword">super</span>.clone();</span><br><span class="line">        } <span class="keyword">catch</span> (CloneNotSupportedException e) {</span><br><span class="line">            <span class="comment">// this shouldn&apos;t happen, since we are Cloneable</span></span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> InternalError(e);</span><br><span class="line">        }</span><br><span class="line">        result.reinitialize();</span><br><span class="line">        result.putMapEntries(<span class="keyword">this</span>, <span class="keyword">false</span>);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// These methods are also used when serializing HashSets</span></span><br><span class="line">    <span class="function"><span class="keyword">final</span> <span class="keyword">float</span> <span class="title">loadFactor</span><span class="params">()</span> </span>{ <span class="keyword">return</span> loadFactor; }</span><br><span class="line">    <span class="function"><span class="keyword">final</span> <span class="keyword">int</span> <span class="title">capacity</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> (table != <span class="keyword">null</span>) ? table.length :</span><br><span class="line">            (threshold &gt; <span class="number">0</span>) ? threshold :</span><br><span class="line">            DEFAULT_INITIAL_CAPACITY;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Save the state of the &lt;tt&gt;HashMap&lt;/tt&gt; instance to a stream (i.e.,</span></span><br><span class="line"><span class="comment">     * serialize it).</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@serialData</span> The &lt;i&gt;capacity&lt;/i&gt; of the HashMap (the length of the</span></span><br><span class="line"><span class="comment">     *             bucket array) is emitted (int), followed by the</span></span><br><span class="line"><span class="comment">     *             &lt;i&gt;size&lt;/i&gt; (an int, the number of key-value</span></span><br><span class="line"><span class="comment">     *             mappings), followed by the key (Object) and value (Object)</span></span><br><span class="line"><span class="comment">     *             for each key-value mapping.  The key-value mappings are</span></span><br><span class="line"><span class="comment">     *             emitted in no particular order.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">writeObject</span><span class="params">(java.io.ObjectOutputStream s)</span></span></span><br><span class="line"><span class="function">        <span class="keyword">throws</span> IOException </span>{</span><br><span class="line">        <span class="keyword">int</span> buckets = capacity();</span><br><span class="line">        <span class="comment">// Write out the threshold, loadfactor, and any hidden stuff</span></span><br><span class="line">        s.defaultWriteObject();</span><br><span class="line">        s.writeInt(buckets);</span><br><span class="line">        s.writeInt(size);</span><br><span class="line">        internalWriteEntries(s);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Reconstitute the {<span class="doctag">@code</span> HashMap} instance from a stream (i.e.,</span></span><br><span class="line"><span class="comment">     * deserialize it).</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">readObject</span><span class="params">(java.io.ObjectInputStream s)</span></span></span><br><span class="line"><span class="function">        <span class="keyword">throws</span> IOException, ClassNotFoundException </span>{</span><br><span class="line">        <span class="comment">// Read in the threshold (ignored), loadfactor, and any hidden stuff</span></span><br><span class="line">        s.defaultReadObject();</span><br><span class="line">        reinitialize();</span><br><span class="line">        <span class="keyword">if</span> (loadFactor &lt;= <span class="number">0</span> || Float.isNaN(loadFactor))</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> InvalidObjectException(<span class="string">&quot;Illegal load factor: &quot;</span> +</span><br><span class="line">                                             loadFactor);</span><br><span class="line">        s.readInt();                <span class="comment">// Read and ignore number of buckets</span></span><br><span class="line">        <span class="keyword">int</span> mappings = s.readInt(); <span class="comment">// Read number of mappings (size)</span></span><br><span class="line">        <span class="keyword">if</span> (mappings &lt; <span class="number">0</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> InvalidObjectException(<span class="string">&quot;Illegal mappings count: &quot;</span> +</span><br><span class="line">                                             mappings);</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (mappings &gt; <span class="number">0</span>) { <span class="comment">// (if zero, use defaults)</span></span><br><span class="line">            <span class="comment">// Size the table using given load factor only if within</span></span><br><span class="line">            <span class="comment">// range of 0.25...4.0</span></span><br><span class="line">            <span class="keyword">float</span> lf = Math.min(Math.max(<span class="number">0.25f</span>, loadFactor), <span class="number">4.0f</span>);</span><br><span class="line">            <span class="keyword">float</span> fc = (<span class="keyword">float</span>)mappings / lf + <span class="number">1.0f</span>;</span><br><span class="line">            <span class="keyword">int</span> cap = ((fc &lt; DEFAULT_INITIAL_CAPACITY) ?</span><br><span class="line">                       DEFAULT_INITIAL_CAPACITY :</span><br><span class="line">                       (fc &gt;= MAXIMUM_CAPACITY) ?</span><br><span class="line">                       MAXIMUM_CAPACITY :</span><br><span class="line">                       tableSizeFor((<span class="keyword">int</span>)fc));</span><br><span class="line">            <span class="keyword">float</span> ft = (<span class="keyword">float</span>)cap * lf;</span><br><span class="line">            threshold = ((cap &lt; MAXIMUM_CAPACITY &amp;&amp; ft &lt; MAXIMUM_CAPACITY) ?</span><br><span class="line">                         (<span class="keyword">int</span>)ft : Integer.MAX_VALUE);</span><br><span class="line">            <span class="meta">@SuppressWarnings</span>({<span class="string">&quot;rawtypes&quot;</span>,<span class="string">&quot;unchecked&quot;</span>})</span><br><span class="line">                Node&lt;K,V&gt;[] tab = (Node&lt;K,V&gt;[])<span class="keyword">new</span> Node[cap];</span><br><span class="line">            table = tab;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// Read the keys and values, and put the mappings in the HashMap</span></span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; mappings; i++) {</span><br><span class="line">                <span class="meta">@SuppressWarnings</span>(<span class="string">&quot;unchecked&quot;</span>)</span><br><span class="line">                    K key = (K) s.readObject();</span><br><span class="line">                <span class="meta">@SuppressWarnings</span>(<span class="string">&quot;unchecked&quot;</span>)</span><br><span class="line">                    V value = (V) s.readObject();</span><br><span class="line">                putVal(hash(key), key, value, <span class="keyword">false</span>, <span class="keyword">false</span>);</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ------------------------------------------------------------ */</span></span><br><span class="line">    <span class="comment">// iterators</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">HashIterator</span> </span>{</span><br><span class="line">        Node&lt;K,V&gt; next;        <span class="comment">// next entry to return</span></span><br><span class="line">        Node&lt;K,V&gt; current;     <span class="comment">// current entry</span></span><br><span class="line">        <span class="keyword">int</span> expectedModCount;  <span class="comment">// for fast-fail</span></span><br><span class="line">        <span class="keyword">int</span> index;             <span class="comment">// current slot</span></span><br><span class="line"></span><br><span class="line">        HashIterator() {</span><br><span class="line">            expectedModCount = modCount;</span><br><span class="line">            Node&lt;K,V&gt;[] t = table;</span><br><span class="line">            current = next = <span class="keyword">null</span>;</span><br><span class="line">            index = <span class="number">0</span>;</span><br><span class="line">            <span class="keyword">if</span> (t != <span class="keyword">null</span> &amp;&amp; size &gt; <span class="number">0</span>) { <span class="comment">// advance to first entry</span></span><br><span class="line">                <span class="keyword">do</span> {} <span class="keyword">while</span> (index &lt; t.length &amp;&amp; (next = t[index++]) == <span class="keyword">null</span>);</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">boolean</span> <span class="title">hasNext</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">return</span> next != <span class="keyword">null</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">final</span> Node&lt;K,V&gt; <span class="title">nextNode</span><span class="params">()</span> </span>{</span><br><span class="line">            Node&lt;K,V&gt;[] t;</span><br><span class="line">            Node&lt;K,V&gt; e = next;</span><br><span class="line">            <span class="keyword">if</span> (modCount != expectedModCount)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">            <span class="keyword">if</span> (e == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> NoSuchElementException();</span><br><span class="line">            <span class="keyword">if</span> ((next = (current = e).next) == <span class="keyword">null</span> &amp;&amp; (t = table) != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">do</span> {} <span class="keyword">while</span> (index &lt; t.length &amp;&amp; (next = t[index++]) == <span class="keyword">null</span>);</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">return</span> e;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title">remove</span><span class="params">()</span> </span>{</span><br><span class="line">            Node&lt;K,V&gt; p = current;</span><br><span class="line">            <span class="keyword">if</span> (p == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException();</span><br><span class="line">            <span class="keyword">if</span> (modCount != expectedModCount)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">            current = <span class="keyword">null</span>;</span><br><span class="line">            K key = p.key;</span><br><span class="line">            removeNode(hash(key), key, <span class="keyword">null</span>, <span class="keyword">false</span>, <span class="keyword">false</span>);</span><br><span class="line">            expectedModCount = modCount;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">KeyIterator</span> <span class="keyword">extends</span> <span class="title">HashIterator</span></span></span><br><span class="line"><span class="class">        <span class="keyword">implements</span> <span class="title">Iterator</span>&lt;<span class="title">K</span>&gt; </span>{</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> K <span class="title">next</span><span class="params">()</span> </span>{ <span class="keyword">return</span> nextNode().key; }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">ValueIterator</span> <span class="keyword">extends</span> <span class="title">HashIterator</span></span></span><br><span class="line"><span class="class">        <span class="keyword">implements</span> <span class="title">Iterator</span>&lt;<span class="title">V</span>&gt; </span>{</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> V <span class="title">next</span><span class="params">()</span> </span>{ <span class="keyword">return</span> nextNode().value; }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">EntryIterator</span> <span class="keyword">extends</span> <span class="title">HashIterator</span></span></span><br><span class="line"><span class="class">        <span class="keyword">implements</span> <span class="title">Iterator</span>&lt;<span class="title">Map</span>.<span class="title">Entry</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;&gt; </span>{</span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">final</span> Map.<span class="function">Entry&lt;K,V&gt; <span class="title">next</span><span class="params">()</span> </span>{ <span class="keyword">return</span> nextNode(); }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ------------------------------------------------------------ */</span></span><br><span class="line">    <span class="comment">// spliterators</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">HashMapSpliterator</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt; </span>{</span><br><span class="line">        <span class="keyword">final</span> HashMap&lt;K,V&gt; map;</span><br><span class="line">        Node&lt;K,V&gt; current;          <span class="comment">// current node</span></span><br><span class="line">        <span class="keyword">int</span> index;                  <span class="comment">// current index, modified on advance/split</span></span><br><span class="line">        <span class="keyword">int</span> fence;                  <span class="comment">// one past last index</span></span><br><span class="line">        <span class="keyword">int</span> est;                    <span class="comment">// size estimate</span></span><br><span class="line">        <span class="keyword">int</span> expectedModCount;       <span class="comment">// for comodification checks</span></span><br><span class="line"></span><br><span class="line">        HashMapSpliterator(HashMap&lt;K,V&gt; m, <span class="keyword">int</span> origin,</span><br><span class="line">                           <span class="keyword">int</span> fence, <span class="keyword">int</span> est,</span><br><span class="line">                           <span class="keyword">int</span> expectedModCount) {</span><br><span class="line">            <span class="keyword">this</span>.map = m;</span><br><span class="line">            <span class="keyword">this</span>.index = origin;</span><br><span class="line">            <span class="keyword">this</span>.fence = fence;</span><br><span class="line">            <span class="keyword">this</span>.est = est;</span><br><span class="line">            <span class="keyword">this</span>.expectedModCount = expectedModCount;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">final</span> <span class="keyword">int</span> <span class="title">getFence</span><span class="params">()</span> </span>{ <span class="comment">// initialize fence and size on first use</span></span><br><span class="line">            <span class="keyword">int</span> hi;</span><br><span class="line">            <span class="keyword">if</span> ((hi = fence) &lt; <span class="number">0</span>) {</span><br><span class="line">                HashMap&lt;K,V&gt; m = map;</span><br><span class="line">                est = m.size;</span><br><span class="line">                expectedModCount = m.modCount;</span><br><span class="line">                Node&lt;K,V&gt;[] tab = m.table;</span><br><span class="line">                hi = fence = (tab == <span class="keyword">null</span>) ? <span class="number">0</span> : tab.length;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">return</span> hi;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">long</span> <span class="title">estimateSize</span><span class="params">()</span> </span>{</span><br><span class="line">            getFence(); <span class="comment">// force init</span></span><br><span class="line">            <span class="keyword">return</span> (<span class="keyword">long</span>) est;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">KeySpliterator</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;</span></span><br><span class="line"><span class="class">        <span class="keyword">extends</span> <span class="title">HashMapSpliterator</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;</span></span><br><span class="line"><span class="class">        <span class="keyword">implements</span> <span class="title">Spliterator</span>&lt;<span class="title">K</span>&gt; </span>{</span><br><span class="line">        KeySpliterator(HashMap&lt;K,V&gt; m, <span class="keyword">int</span> origin, <span class="keyword">int</span> fence, <span class="keyword">int</span> est,</span><br><span class="line">                       <span class="keyword">int</span> expectedModCount) {</span><br><span class="line">            <span class="keyword">super</span>(m, origin, fence, est, expectedModCount);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> KeySpliterator&lt;K,V&gt; <span class="title">trySplit</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> hi = getFence(), lo = index, mid = (lo + hi) &gt;&gt;&gt; <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">return</span> (lo &gt;= mid || current != <span class="keyword">null</span>) ? <span class="keyword">null</span> :</span><br><span class="line">                <span class="keyword">new</span> KeySpliterator&lt;&gt;(map, lo, index = mid, est &gt;&gt;&gt;= <span class="number">1</span>,</span><br><span class="line">                                        expectedModCount);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">forEachRemaining</span><span class="params">(Consumer&lt;? <span class="keyword">super</span> K&gt; action)</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> i, hi, mc;</span><br><span class="line">            <span class="keyword">if</span> (action == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">            HashMap&lt;K,V&gt; m = map;</span><br><span class="line">            Node&lt;K,V&gt;[] tab = m.table;</span><br><span class="line">            <span class="keyword">if</span> ((hi = fence) &lt; <span class="number">0</span>) {</span><br><span class="line">                mc = expectedModCount = m.modCount;</span><br><span class="line">                hi = fence = (tab == <span class="keyword">null</span>) ? <span class="number">0</span> : tab.length;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                mc = expectedModCount;</span><br><span class="line">            <span class="keyword">if</span> (tab != <span class="keyword">null</span> &amp;&amp; tab.length &gt;= hi &amp;&amp;</span><br><span class="line">                (i = index) &gt;= <span class="number">0</span> &amp;&amp; (i &lt; (index = hi) || current != <span class="keyword">null</span>)) {</span><br><span class="line">                Node&lt;K,V&gt; p = current;</span><br><span class="line">                current = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">do</span> {</span><br><span class="line">                    <span class="keyword">if</span> (p == <span class="keyword">null</span>)</span><br><span class="line">                        p = tab[i++];</span><br><span class="line">                    <span class="keyword">else</span> {</span><br><span class="line">                        action.accept(p.key);</span><br><span class="line">                        p = p.next;</span><br><span class="line">                    }</span><br><span class="line">                } <span class="keyword">while</span> (p != <span class="keyword">null</span> || i &lt; hi);</span><br><span class="line">                <span class="keyword">if</span> (m.modCount != mc)</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">tryAdvance</span><span class="params">(Consumer&lt;? <span class="keyword">super</span> K&gt; action)</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> hi;</span><br><span class="line">            <span class="keyword">if</span> (action == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">            Node&lt;K,V&gt;[] tab = map.table;</span><br><span class="line">            <span class="keyword">if</span> (tab != <span class="keyword">null</span> &amp;&amp; tab.length &gt;= (hi = getFence()) &amp;&amp; index &gt;= <span class="number">0</span>) {</span><br><span class="line">                <span class="keyword">while</span> (current != <span class="keyword">null</span> || index &lt; hi) {</span><br><span class="line">                    <span class="keyword">if</span> (current == <span class="keyword">null</span>)</span><br><span class="line">                        current = tab[index++];</span><br><span class="line">                    <span class="keyword">else</span> {</span><br><span class="line">                        K k = current.key;</span><br><span class="line">                        current = current.next;</span><br><span class="line">                        action.accept(k);</span><br><span class="line">                        <span class="keyword">if</span> (map.modCount != expectedModCount)</span><br><span class="line">                            <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">                        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">characteristics</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">return</span> (fence &lt; <span class="number">0</span> || est == map.size ? Spliterator.SIZED : <span class="number">0</span>) |</span><br><span class="line">                Spliterator.DISTINCT;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">ValueSpliterator</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;</span></span><br><span class="line"><span class="class">        <span class="keyword">extends</span> <span class="title">HashMapSpliterator</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;</span></span><br><span class="line"><span class="class">        <span class="keyword">implements</span> <span class="title">Spliterator</span>&lt;<span class="title">V</span>&gt; </span>{</span><br><span class="line">        ValueSpliterator(HashMap&lt;K,V&gt; m, <span class="keyword">int</span> origin, <span class="keyword">int</span> fence, <span class="keyword">int</span> est,</span><br><span class="line">                         <span class="keyword">int</span> expectedModCount) {</span><br><span class="line">            <span class="keyword">super</span>(m, origin, fence, est, expectedModCount);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> ValueSpliterator&lt;K,V&gt; <span class="title">trySplit</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> hi = getFence(), lo = index, mid = (lo + hi) &gt;&gt;&gt; <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">return</span> (lo &gt;= mid || current != <span class="keyword">null</span>) ? <span class="keyword">null</span> :</span><br><span class="line">                <span class="keyword">new</span> ValueSpliterator&lt;&gt;(map, lo, index = mid, est &gt;&gt;&gt;= <span class="number">1</span>,</span><br><span class="line">                                          expectedModCount);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">forEachRemaining</span><span class="params">(Consumer&lt;? <span class="keyword">super</span> V&gt; action)</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> i, hi, mc;</span><br><span class="line">            <span class="keyword">if</span> (action == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">            HashMap&lt;K,V&gt; m = map;</span><br><span class="line">            Node&lt;K,V&gt;[] tab = m.table;</span><br><span class="line">            <span class="keyword">if</span> ((hi = fence) &lt; <span class="number">0</span>) {</span><br><span class="line">                mc = expectedModCount = m.modCount;</span><br><span class="line">                hi = fence = (tab == <span class="keyword">null</span>) ? <span class="number">0</span> : tab.length;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                mc = expectedModCount;</span><br><span class="line">            <span class="keyword">if</span> (tab != <span class="keyword">null</span> &amp;&amp; tab.length &gt;= hi &amp;&amp;</span><br><span class="line">                (i = index) &gt;= <span class="number">0</span> &amp;&amp; (i &lt; (index = hi) || current != <span class="keyword">null</span>)) {</span><br><span class="line">                Node&lt;K,V&gt; p = current;</span><br><span class="line">                current = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">do</span> {</span><br><span class="line">                    <span class="keyword">if</span> (p == <span class="keyword">null</span>)</span><br><span class="line">                        p = tab[i++];</span><br><span class="line">                    <span class="keyword">else</span> {</span><br><span class="line">                        action.accept(p.value);</span><br><span class="line">                        p = p.next;</span><br><span class="line">                    }</span><br><span class="line">                } <span class="keyword">while</span> (p != <span class="keyword">null</span> || i &lt; hi);</span><br><span class="line">                <span class="keyword">if</span> (m.modCount != mc)</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">tryAdvance</span><span class="params">(Consumer&lt;? <span class="keyword">super</span> V&gt; action)</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> hi;</span><br><span class="line">            <span class="keyword">if</span> (action == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">            Node&lt;K,V&gt;[] tab = map.table;</span><br><span class="line">            <span class="keyword">if</span> (tab != <span class="keyword">null</span> &amp;&amp; tab.length &gt;= (hi = getFence()) &amp;&amp; index &gt;= <span class="number">0</span>) {</span><br><span class="line">                <span class="keyword">while</span> (current != <span class="keyword">null</span> || index &lt; hi) {</span><br><span class="line">                    <span class="keyword">if</span> (current == <span class="keyword">null</span>)</span><br><span class="line">                        current = tab[index++];</span><br><span class="line">                    <span class="keyword">else</span> {</span><br><span class="line">                        V v = current.value;</span><br><span class="line">                        current = current.next;</span><br><span class="line">                        action.accept(v);</span><br><span class="line">                        <span class="keyword">if</span> (map.modCount != expectedModCount)</span><br><span class="line">                            <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">                        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">characteristics</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">return</span> (fence &lt; <span class="number">0</span> || est == map.size ? Spliterator.SIZED : <span class="number">0</span>);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">EntrySpliterator</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;</span></span><br><span class="line"><span class="class">        <span class="keyword">extends</span> <span class="title">HashMapSpliterator</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;</span></span><br><span class="line"><span class="class">        <span class="keyword">implements</span> <span class="title">Spliterator</span>&lt;<span class="title">Map</span>.<span class="title">Entry</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt;&gt; </span>{</span><br><span class="line">        EntrySpliterator(HashMap&lt;K,V&gt; m, <span class="keyword">int</span> origin, <span class="keyword">int</span> fence, <span class="keyword">int</span> est,</span><br><span class="line">                         <span class="keyword">int</span> expectedModCount) {</span><br><span class="line">            <span class="keyword">super</span>(m, origin, fence, est, expectedModCount);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> EntrySpliterator&lt;K,V&gt; <span class="title">trySplit</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> hi = getFence(), lo = index, mid = (lo + hi) &gt;&gt;&gt; <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">return</span> (lo &gt;= mid || current != <span class="keyword">null</span>) ? <span class="keyword">null</span> :</span><br><span class="line">                <span class="keyword">new</span> EntrySpliterator&lt;&gt;(map, lo, index = mid, est &gt;&gt;&gt;= <span class="number">1</span>,</span><br><span class="line">                                          expectedModCount);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">forEachRemaining</span><span class="params">(Consumer&lt;? <span class="keyword">super</span> Map.Entry&lt;K,V&gt;&gt; action)</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> i, hi, mc;</span><br><span class="line">            <span class="keyword">if</span> (action == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">            HashMap&lt;K,V&gt; m = map;</span><br><span class="line">            Node&lt;K,V&gt;[] tab = m.table;</span><br><span class="line">            <span class="keyword">if</span> ((hi = fence) &lt; <span class="number">0</span>) {</span><br><span class="line">                mc = expectedModCount = m.modCount;</span><br><span class="line">                hi = fence = (tab == <span class="keyword">null</span>) ? <span class="number">0</span> : tab.length;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                mc = expectedModCount;</span><br><span class="line">            <span class="keyword">if</span> (tab != <span class="keyword">null</span> &amp;&amp; tab.length &gt;= hi &amp;&amp;</span><br><span class="line">                (i = index) &gt;= <span class="number">0</span> &amp;&amp; (i &lt; (index = hi) || current != <span class="keyword">null</span>)) {</span><br><span class="line">                Node&lt;K,V&gt; p = current;</span><br><span class="line">                current = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">do</span> {</span><br><span class="line">                    <span class="keyword">if</span> (p == <span class="keyword">null</span>)</span><br><span class="line">                        p = tab[i++];</span><br><span class="line">                    <span class="keyword">else</span> {</span><br><span class="line">                        action.accept(p);</span><br><span class="line">                        p = p.next;</span><br><span class="line">                    }</span><br><span class="line">                } <span class="keyword">while</span> (p != <span class="keyword">null</span> || i &lt; hi);</span><br><span class="line">                <span class="keyword">if</span> (m.modCount != mc)</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">tryAdvance</span><span class="params">(Consumer&lt;? <span class="keyword">super</span> Map.Entry&lt;K,V&gt;&gt; action)</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> hi;</span><br><span class="line">            <span class="keyword">if</span> (action == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">            Node&lt;K,V&gt;[] tab = map.table;</span><br><span class="line">            <span class="keyword">if</span> (tab != <span class="keyword">null</span> &amp;&amp; tab.length &gt;= (hi = getFence()) &amp;&amp; index &gt;= <span class="number">0</span>) {</span><br><span class="line">                <span class="keyword">while</span> (current != <span class="keyword">null</span> || index &lt; hi) {</span><br><span class="line">                    <span class="keyword">if</span> (current == <span class="keyword">null</span>)</span><br><span class="line">                        current = tab[index++];</span><br><span class="line">                    <span class="keyword">else</span> {</span><br><span class="line">                        Node&lt;K,V&gt; e = current;</span><br><span class="line">                        current = current.next;</span><br><span class="line">                        action.accept(e);</span><br><span class="line">                        <span class="keyword">if</span> (map.modCount != expectedModCount)</span><br><span class="line">                            <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();</span><br><span class="line">                        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">characteristics</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">return</span> (fence &lt; <span class="number">0</span> || est == map.size ? Spliterator.SIZED : <span class="number">0</span>) |</span><br><span class="line">                Spliterator.DISTINCT;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ------------------------------------------------------------ */</span></span><br><span class="line">    <span class="comment">// LinkedHashMap support</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * The following package-protected methods are designed to be</span></span><br><span class="line"><span class="comment">     * overridden by LinkedHashMap, but not by any other subclass.</span></span><br><span class="line"><span class="comment">     * Nearly all other internal methods are also package-protected</span></span><br><span class="line"><span class="comment">     * but are declared final, so can be used by LinkedHashMap, view</span></span><br><span class="line"><span class="comment">     * classes, and HashSet.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Create a regular (non-tree) node</span></span><br><span class="line">    <span class="function">Node&lt;K,V&gt; <span class="title">newNode</span><span class="params">(<span class="keyword">int</span> hash, K key, V value, Node&lt;K,V&gt; next)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Node&lt;&gt;(hash, key, value, next);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// For conversion from TreeNodes to plain nodes</span></span><br><span class="line">    <span class="function">Node&lt;K,V&gt; <span class="title">replacementNode</span><span class="params">(Node&lt;K,V&gt; p, Node&lt;K,V&gt; next)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Node&lt;&gt;(p.hash, p.key, p.value, next);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Create a tree bin node</span></span><br><span class="line">    <span class="function">TreeNode&lt;K,V&gt; <span class="title">newTreeNode</span><span class="params">(<span class="keyword">int</span> hash, K key, V value, Node&lt;K,V&gt; next)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> TreeNode&lt;&gt;(hash, key, value, next);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// For treeifyBin</span></span><br><span class="line">    <span class="function">TreeNode&lt;K,V&gt; <span class="title">replacementTreeNode</span><span class="params">(Node&lt;K,V&gt; p, Node&lt;K,V&gt; next)</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> TreeNode&lt;&gt;(p.hash, p.key, p.value, next);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Reset to initial default state.  Called by clone and readObject.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">reinitialize</span><span class="params">()</span> </span>{</span><br><span class="line">        table = <span class="keyword">null</span>;</span><br><span class="line">        entrySet = <span class="keyword">null</span>;</span><br><span class="line">        keySet = <span class="keyword">null</span>;</span><br><span class="line">        values = <span class="keyword">null</span>;</span><br><span class="line">        modCount = <span class="number">0</span>;</span><br><span class="line">        threshold = <span class="number">0</span>;</span><br><span class="line">        size = <span class="number">0</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Callbacks to allow LinkedHashMap post-actions</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">afterNodeAccess</span><span class="params">(Node&lt;K,V&gt; p)</span> </span>{ }</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">afterNodeInsertion</span><span class="params">(<span class="keyword">boolean</span> evict)</span> </span>{ }</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">afterNodeRemoval</span><span class="params">(Node&lt;K,V&gt; p)</span> </span>{ }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Called only from writeObject, to ensure compatible ordering.</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">internalWriteEntries</span><span class="params">(java.io.ObjectOutputStream s)</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line">        Node&lt;K,V&gt;[] tab;</span><br><span class="line">        <span class="keyword">if</span> (size &gt; <span class="number">0</span> &amp;&amp; (tab = table) != <span class="keyword">null</span>) {</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; tab.length; ++i) {</span><br><span class="line">                <span class="keyword">for</span> (Node&lt;K,V&gt; e = tab[i]; e != <span class="keyword">null</span>; e = e.next) {</span><br><span class="line">                    s.writeObject(e.key);</span><br><span class="line">                    s.writeObject(e.value);</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ------------------------------------------------------------ */</span></span><br><span class="line">    <span class="comment">// Tree bins</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Entry for Tree bins. Extends LinkedHashMap.Entry (which in turn</span></span><br><span class="line"><span class="comment">     * extends Node) so can be used as extension of either regular or</span></span><br><span class="line"><span class="comment">     * linked node.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">TreeNode</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt; <span class="keyword">extends</span> <span class="title">LinkedHashMap</span>.<span class="title">Entry</span>&lt;<span class="title">K</span>,<span class="title">V</span>&gt; </span>{</span><br><span class="line">        TreeNode&lt;K,V&gt; parent;  <span class="comment">// red-black tree links</span></span><br><span class="line">        TreeNode&lt;K,V&gt; left;</span><br><span class="line">        TreeNode&lt;K,V&gt; right;</span><br><span class="line">        TreeNode&lt;K,V&gt; prev;    <span class="comment">// needed to unlink next upon deletion</span></span><br><span class="line">        <span class="keyword">boolean</span> red;</span><br><span class="line">        TreeNode(<span class="keyword">int</span> hash, K key, V val, Node&lt;K,V&gt; next) {</span><br><span class="line">            <span class="keyword">super</span>(hash, key, val, next);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Returns root of tree containing this node.</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="function"><span class="keyword">final</span> TreeNode&lt;K,V&gt; <span class="title">root</span><span class="params">()</span> </span>{</span><br><span class="line">            <span class="keyword">for</span> (TreeNode&lt;K,V&gt; r = <span class="keyword">this</span>, p;;) {</span><br><span class="line">                <span class="keyword">if</span> ((p = r.parent) == <span class="keyword">null</span>)</span><br><span class="line">                    <span class="keyword">return</span> r;</span><br><span class="line">                r = p;</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Ensures that the given root is the first node of its bin.</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="keyword">static</span> &lt;K,V&gt; <span class="function"><span class="keyword">void</span> <span class="title">moveRootToFront</span><span class="params">(Node&lt;K,V&gt;[] tab, TreeNode&lt;K,V&gt; root)</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> n;</span><br><span class="line">            <span class="keyword">if</span> (root != <span class="keyword">null</span> &amp;&amp; tab != <span class="keyword">null</span> &amp;&amp; (n = tab.length) &gt; <span class="number">0</span>) {</span><br><span class="line">                <span class="keyword">int</span> index = (n - <span class="number">1</span>) &amp; root.hash;</span><br><span class="line">                TreeNode&lt;K,V&gt; first = (TreeNode&lt;K,V&gt;)tab[index];</span><br><span class="line">                <span class="keyword">if</span> (root != first) {</span><br><span class="line">                    Node&lt;K,V&gt; rn;</span><br><span class="line">                    tab[index] = root;</span><br><span class="line">                    TreeNode&lt;K,V&gt; rp = root.prev;</span><br><span class="line">                    <span class="keyword">if</span> ((rn = root.next) != <span class="keyword">null</span>)</span><br><span class="line">                        ((TreeNode&lt;K,V&gt;)rn).prev = rp;</span><br><span class="line">                    <span class="keyword">if</span> (rp != <span class="keyword">null</span>)</span><br><span class="line">                        rp.next = rn;</span><br><span class="line">                    <span class="keyword">if</span> (first != <span class="keyword">null</span>)</span><br><span class="line">                        first.prev = root;</span><br><span class="line">                    root.next = first;</span><br><span class="line">                    root.prev = <span class="keyword">null</span>;</span><br><span class="line">                }</span><br><span class="line">                <span class="function"><span class="keyword">assert</span> <span class="title">checkInvariants</span><span class="params">(root)</span></span>;</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Finds the node starting at root p with the given hash and key.</span></span><br><span class="line"><span class="comment">         * The kc argument caches comparableClassFor(key) upon first use</span></span><br><span class="line"><span class="comment">         * comparing keys.</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="function"><span class="keyword">final</span> TreeNode&lt;K,V&gt; <span class="title">find</span><span class="params">(<span class="keyword">int</span> h, Object k, Class&lt;?&gt; kc)</span> </span>{</span><br><span class="line">            TreeNode&lt;K,V&gt; p = <span class="keyword">this</span>;</span><br><span class="line">            <span class="keyword">do</span> {</span><br><span class="line">                <span class="keyword">int</span> ph, dir; K pk;</span><br><span class="line">                TreeNode&lt;K,V&gt; pl = p.left, pr = p.right, q;</span><br><span class="line">                <span class="keyword">if</span> ((ph = p.hash) &gt; h)</span><br><span class="line">                    p = pl;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (ph &lt; h)</span><br><span class="line">                    p = pr;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> ((pk = p.key) == k || (k != <span class="keyword">null</span> &amp;&amp; k.equals(pk)))</span><br><span class="line">                    <span class="keyword">return</span> p;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (pl == <span class="keyword">null</span>)</span><br><span class="line">                    p = pr;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (pr == <span class="keyword">null</span>)</span><br><span class="line">                    p = pl;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> ((kc != <span class="keyword">null</span> ||</span><br><span class="line">                          (kc = comparableClassFor(k)) != <span class="keyword">null</span>) &amp;&amp;</span><br><span class="line">                         (dir = compareComparables(kc, k, pk)) != <span class="number">0</span>)</span><br><span class="line">                    p = (dir &lt; <span class="number">0</span>) ? pl : pr;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> ((q = pr.find(h, k, kc)) != <span class="keyword">null</span>)</span><br><span class="line">                    <span class="keyword">return</span> q;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    p = pl;</span><br><span class="line">            } <span class="keyword">while</span> (p != <span class="keyword">null</span>);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Calls find for root node.</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="function"><span class="keyword">final</span> TreeNode&lt;K,V&gt; <span class="title">getTreeNode</span><span class="params">(<span class="keyword">int</span> h, Object k)</span> </span>{</span><br><span class="line">            <span class="keyword">return</span> ((parent != <span class="keyword">null</span>) ? root() : <span class="keyword">this</span>).find(h, k, <span class="keyword">null</span>);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Tie-breaking utility for ordering insertions when equal</span></span><br><span class="line"><span class="comment">         * hashCodes and non-comparable. We don&apos;t require a total</span></span><br><span class="line"><span class="comment">         * order, just a consistent insertion rule to maintain</span></span><br><span class="line"><span class="comment">         * equivalence across rebalancings. Tie-breaking further than</span></span><br><span class="line"><span class="comment">         * necessary simplifies testing a bit.</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">tieBreakOrder</span><span class="params">(Object a, Object b)</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> d;</span><br><span class="line">            <span class="keyword">if</span> (a == <span class="keyword">null</span> || b == <span class="keyword">null</span> ||</span><br><span class="line">                (d = a.getClass().getName().</span><br><span class="line">                 compareTo(b.getClass().getName())) == <span class="number">0</span>)</span><br><span class="line">                d = (System.identityHashCode(a) &lt;= System.identityHashCode(b) ?</span><br><span class="line">                     -<span class="number">1</span> : <span class="number">1</span>);</span><br><span class="line">            <span class="keyword">return</span> d;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Forms tree of the nodes linked from this node.</span></span><br><span class="line"><span class="comment">         * <span class="doctag">@return</span> root of tree</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="function"><span class="keyword">final</span> <span class="keyword">void</span> <span class="title">treeify</span><span class="params">(Node&lt;K,V&gt;[] tab)</span> </span>{</span><br><span class="line">            TreeNode&lt;K,V&gt; root = <span class="keyword">null</span>;</span><br><span class="line">            <span class="keyword">for</span> (TreeNode&lt;K,V&gt; x = <span class="keyword">this</span>, next; x != <span class="keyword">null</span>; x = next) {</span><br><span class="line">                next = (TreeNode&lt;K,V&gt;)x.next;</span><br><span class="line">                x.left = x.right = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">if</span> (root == <span class="keyword">null</span>) {</span><br><span class="line">                    x.parent = <span class="keyword">null</span>;</span><br><span class="line">                    x.red = <span class="keyword">false</span>;</span><br><span class="line">                    root = x;</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">else</span> {</span><br><span class="line">                    K k = x.key;</span><br><span class="line">                    <span class="keyword">int</span> h = x.hash;</span><br><span class="line">                    Class&lt;?&gt; kc = <span class="keyword">null</span>;</span><br><span class="line">                    <span class="keyword">for</span> (TreeNode&lt;K,V&gt; p = root;;) {</span><br><span class="line">                        <span class="keyword">int</span> dir, ph;</span><br><span class="line">                        K pk = p.key;</span><br><span class="line">                        <span class="keyword">if</span> ((ph = p.hash) &gt; h)</span><br><span class="line">                            dir = -<span class="number">1</span>;</span><br><span class="line">                        <span class="keyword">else</span> <span class="keyword">if</span> (ph &lt; h)</span><br><span class="line">                            dir = <span class="number">1</span>;</span><br><span class="line">                        <span class="keyword">else</span> <span class="keyword">if</span> ((kc == <span class="keyword">null</span> &amp;&amp;</span><br><span class="line">                                  (kc = comparableClassFor(k)) == <span class="keyword">null</span>) ||</span><br><span class="line">                                 (dir = compareComparables(kc, k, pk)) == <span class="number">0</span>)</span><br><span class="line">                            dir = tieBreakOrder(k, pk);</span><br><span class="line"></span><br><span class="line">                        TreeNode&lt;K,V&gt; xp = p;</span><br><span class="line">                        <span class="keyword">if</span> ((p = (dir &lt;= <span class="number">0</span>) ? p.left : p.right) == <span class="keyword">null</span>) {</span><br><span class="line">                            x.parent = xp;</span><br><span class="line">                            <span class="keyword">if</span> (dir &lt;= <span class="number">0</span>)</span><br><span class="line">                                xp.left = x;</span><br><span class="line">                            <span class="keyword">else</span></span><br><span class="line">                                xp.right = x;</span><br><span class="line">                            root = balanceInsertion(root, x);</span><br><span class="line">                            <span class="keyword">break</span>;</span><br><span class="line">                        }</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            moveRootToFront(tab, root);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Returns a list of non-TreeNodes replacing those linked from</span></span><br><span class="line"><span class="comment">         * this node.</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="function"><span class="keyword">final</span> Node&lt;K,V&gt; <span class="title">untreeify</span><span class="params">(HashMap&lt;K,V&gt; map)</span> </span>{</span><br><span class="line">            Node&lt;K,V&gt; hd = <span class="keyword">null</span>, tl = <span class="keyword">null</span>;</span><br><span class="line">            <span class="keyword">for</span> (Node&lt;K,V&gt; q = <span class="keyword">this</span>; q != <span class="keyword">null</span>; q = q.next) {</span><br><span class="line">                Node&lt;K,V&gt; p = map.replacementNode(q, <span class="keyword">null</span>);</span><br><span class="line">                <span class="keyword">if</span> (tl == <span class="keyword">null</span>)</span><br><span class="line">                    hd = p;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    tl.next = p;</span><br><span class="line">                tl = p;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">return</span> hd;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Tree version of putVal.</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="function"><span class="keyword">final</span> TreeNode&lt;K,V&gt; <span class="title">putTreeVal</span><span class="params">(HashMap&lt;K,V&gt; map, Node&lt;K,V&gt;[] tab,</span></span></span><br><span class="line"><span class="function"><span class="params">                                       <span class="keyword">int</span> h, K k, V v)</span> </span>{</span><br><span class="line">            Class&lt;?&gt; kc = <span class="keyword">null</span>;</span><br><span class="line">            <span class="keyword">boolean</span> searched = <span class="keyword">false</span>;</span><br><span class="line">            TreeNode&lt;K,V&gt; root = (parent != <span class="keyword">null</span>) ? root() : <span class="keyword">this</span>;</span><br><span class="line">            <span class="keyword">for</span> (TreeNode&lt;K,V&gt; p = root;;) {</span><br><span class="line">                <span class="keyword">int</span> dir, ph; K pk;</span><br><span class="line">                <span class="keyword">if</span> ((ph = p.hash) &gt; h)</span><br><span class="line">                    dir = -<span class="number">1</span>;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (ph &lt; h)</span><br><span class="line">                    dir = <span class="number">1</span>;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> ((pk = p.key) == k || (k != <span class="keyword">null</span> &amp;&amp; k.equals(pk)))</span><br><span class="line">                    <span class="keyword">return</span> p;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> ((kc == <span class="keyword">null</span> &amp;&amp;</span><br><span class="line">                          (kc = comparableClassFor(k)) == <span class="keyword">null</span>) ||</span><br><span class="line">                         (dir = compareComparables(kc, k, pk)) == <span class="number">0</span>) {</span><br><span class="line">                    <span class="keyword">if</span> (!searched) {</span><br><span class="line">                        TreeNode&lt;K,V&gt; q, ch;</span><br><span class="line">                        searched = <span class="keyword">true</span>;</span><br><span class="line">                        <span class="keyword">if</span> (((ch = p.left) != <span class="keyword">null</span> &amp;&amp;</span><br><span class="line">                             (q = ch.find(h, k, kc)) != <span class="keyword">null</span>) ||</span><br><span class="line">                            ((ch = p.right) != <span class="keyword">null</span> &amp;&amp;</span><br><span class="line">                             (q = ch.find(h, k, kc)) != <span class="keyword">null</span>))</span><br><span class="line">                            <span class="keyword">return</span> q;</span><br><span class="line">                    }</span><br><span class="line">                    dir = tieBreakOrder(k, pk);</span><br><span class="line">                }</span><br><span class="line"></span><br><span class="line">                TreeNode&lt;K,V&gt; xp = p;</span><br><span class="line">                <span class="keyword">if</span> ((p = (dir &lt;= <span class="number">0</span>) ? p.left : p.right) == <span class="keyword">null</span>) {</span><br><span class="line">                    Node&lt;K,V&gt; xpn = xp.next;</span><br><span class="line">                    TreeNode&lt;K,V&gt; x = map.newTreeNode(h, k, v, xpn);</span><br><span class="line">                    <span class="keyword">if</span> (dir &lt;= <span class="number">0</span>)</span><br><span class="line">                        xp.left = x;</span><br><span class="line">                    <span class="keyword">else</span></span><br><span class="line">                        xp.right = x;</span><br><span class="line">                    xp.next = x;</span><br><span class="line">                    x.parent = x.prev = xp;</span><br><span class="line">                    <span class="keyword">if</span> (xpn != <span class="keyword">null</span>)</span><br><span class="line">                        ((TreeNode&lt;K,V&gt;)xpn).prev = x;</span><br><span class="line">                    moveRootToFront(tab, balanceInsertion(root, x));</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Removes the given node, that must be present before this call.</span></span><br><span class="line"><span class="comment">         * This is messier than typical red-black deletion code because we</span></span><br><span class="line"><span class="comment">         * cannot swap the contents of an interior node with a leaf</span></span><br><span class="line"><span class="comment">         * successor that is pinned by &quot;next&quot; pointers that are accessible</span></span><br><span class="line"><span class="comment">         * independently during traversal. So instead we swap the tree</span></span><br><span class="line"><span class="comment">         * linkages. If the current tree appears to have too few nodes,</span></span><br><span class="line"><span class="comment">         * the bin is converted back to a plain bin. (The test triggers</span></span><br><span class="line"><span class="comment">         * somewhere between 2 and 6 nodes, depending on tree structure).</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="function"><span class="keyword">final</span> <span class="keyword">void</span> <span class="title">removeTreeNode</span><span class="params">(HashMap&lt;K,V&gt; map, Node&lt;K,V&gt;[] tab,</span></span></span><br><span class="line"><span class="function"><span class="params">                                  <span class="keyword">boolean</span> movable)</span> </span>{</span><br><span class="line">            <span class="keyword">int</span> n;</span><br><span class="line">            <span class="keyword">if</span> (tab == <span class="keyword">null</span> || (n = tab.length) == <span class="number">0</span>)</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            <span class="keyword">int</span> index = (n - <span class="number">1</span>) &amp; hash;</span><br><span class="line">            TreeNode&lt;K,V&gt; first = (TreeNode&lt;K,V&gt;)tab[index], root = first, rl;</span><br><span class="line">            TreeNode&lt;K,V&gt; succ = (TreeNode&lt;K,V&gt;)next, pred = prev;</span><br><span class="line">            <span class="keyword">if</span> (pred == <span class="keyword">null</span>)</span><br><span class="line">                tab[index] = first = succ;</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                pred.next = succ;</span><br><span class="line">            <span class="keyword">if</span> (succ != <span class="keyword">null</span>)</span><br><span class="line">                succ.prev = pred;</span><br><span class="line">            <span class="keyword">if</span> (first == <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            <span class="keyword">if</span> (root.parent != <span class="keyword">null</span>)</span><br><span class="line">                root = root.root();</span><br><span class="line">            <span class="keyword">if</span> (root == <span class="keyword">null</span> || root.right == <span class="keyword">null</span> ||</span><br><span class="line">                (rl = root.left) == <span class="keyword">null</span> || rl.left == <span class="keyword">null</span>) {</span><br><span class="line">                tab[index] = first.untreeify(map);  <span class="comment">// too small</span></span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            }</span><br><span class="line">            TreeNode&lt;K,V&gt; p = <span class="keyword">this</span>, pl = left, pr = right, replacement;</span><br><span class="line">            <span class="keyword">if</span> (pl != <span class="keyword">null</span> &amp;&amp; pr != <span class="keyword">null</span>) {</span><br><span class="line">                TreeNode&lt;K,V&gt; s = pr, sl;</span><br><span class="line">                <span class="keyword">while</span> ((sl = s.left) != <span class="keyword">null</span>) <span class="comment">// find successor</span></span><br><span class="line">                    s = sl;</span><br><span class="line">                <span class="keyword">boolean</span> c = s.red; s.red = p.red; p.red = c; <span class="comment">// swap colors</span></span><br><span class="line">                TreeNode&lt;K,V&gt; sr = s.right;</span><br><span class="line">                TreeNode&lt;K,V&gt; pp = p.parent;</span><br><span class="line">                <span class="keyword">if</span> (s == pr) { <span class="comment">// p was s&apos;s direct parent</span></span><br><span class="line">                    p.parent = s;</span><br><span class="line">                    s.right = p;</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">else</span> {</span><br><span class="line">                    TreeNode&lt;K,V&gt; sp = s.parent;</span><br><span class="line">                    <span class="keyword">if</span> ((p.parent = sp) != <span class="keyword">null</span>) {</span><br><span class="line">                        <span class="keyword">if</span> (s == sp.left)</span><br><span class="line">                            sp.left = p;</span><br><span class="line">                        <span class="keyword">else</span></span><br><span class="line">                            sp.right = p;</span><br><span class="line">                    }</span><br><span class="line">                    <span class="keyword">if</span> ((s.right = pr) != <span class="keyword">null</span>)</span><br><span class="line">                        pr.parent = s;</span><br><span class="line">                }</span><br><span class="line">                p.left = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">if</span> ((p.right = sr) != <span class="keyword">null</span>)</span><br><span class="line">                    sr.parent = p;</span><br><span class="line">                <span class="keyword">if</span> ((s.left = pl) != <span class="keyword">null</span>)</span><br><span class="line">                    pl.parent = s;</span><br><span class="line">                <span class="keyword">if</span> ((s.parent = pp) == <span class="keyword">null</span>)</span><br><span class="line">                    root = s;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (p == pp.left)</span><br><span class="line">                    pp.left = s;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    pp.right = s;</span><br><span class="line">                <span class="keyword">if</span> (sr != <span class="keyword">null</span>)</span><br><span class="line">                    replacement = sr;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    replacement = p;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> (pl != <span class="keyword">null</span>)</span><br><span class="line">                replacement = pl;</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> (pr != <span class="keyword">null</span>)</span><br><span class="line">                replacement = pr;</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                replacement = p;</span><br><span class="line">            <span class="keyword">if</span> (replacement != p) {</span><br><span class="line">                TreeNode&lt;K,V&gt; pp = replacement.parent = p.parent;</span><br><span class="line">                <span class="keyword">if</span> (pp == <span class="keyword">null</span>)</span><br><span class="line">                    root = replacement;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (p == pp.left)</span><br><span class="line">                    pp.left = replacement;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    pp.right = replacement;</span><br><span class="line">                p.left = p.right = p.parent = <span class="keyword">null</span>;</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">            TreeNode&lt;K,V&gt; r = p.red ? root : balanceDeletion(root, replacement);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (replacement == p) {  <span class="comment">// detach</span></span><br><span class="line">                TreeNode&lt;K,V&gt; pp = p.parent;</span><br><span class="line">                p.parent = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">if</span> (pp != <span class="keyword">null</span>) {</span><br><span class="line">                    <span class="keyword">if</span> (p == pp.left)</span><br><span class="line">                        pp.left = <span class="keyword">null</span>;</span><br><span class="line">                    <span class="keyword">else</span> <span class="keyword">if</span> (p == pp.right)</span><br><span class="line">                        pp.right = <span class="keyword">null</span>;</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">if</span> (movable)</span><br><span class="line">                moveRootToFront(tab, r);</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Splits nodes in a tree bin into lower and upper tree bins,</span></span><br><span class="line"><span class="comment">         * or untreeifies if now too small. Called only from resize;</span></span><br><span class="line"><span class="comment">         * see above discussion about split bits and indices.</span></span><br><span class="line"><span class="comment">         *</span></span><br><span class="line"><span class="comment">         * <span class="doctag">@param</span> map the map</span></span><br><span class="line"><span class="comment">         * <span class="doctag">@param</span> tab the table for recording bin heads</span></span><br><span class="line"><span class="comment">         * <span class="doctag">@param</span> index the index of the table being split</span></span><br><span class="line"><span class="comment">         * <span class="doctag">@param</span> bit the bit of hash to split on</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="function"><span class="keyword">final</span> <span class="keyword">void</span> <span class="title">split</span><span class="params">(HashMap&lt;K,V&gt; map, Node&lt;K,V&gt;[] tab, <span class="keyword">int</span> index, <span class="keyword">int</span> bit)</span> </span>{</span><br><span class="line">            TreeNode&lt;K,V&gt; b = <span class="keyword">this</span>;</span><br><span class="line">            <span class="comment">// Relink into lo and hi lists, preserving order</span></span><br><span class="line">            TreeNode&lt;K,V&gt; loHead = <span class="keyword">null</span>, loTail = <span class="keyword">null</span>;</span><br><span class="line">            TreeNode&lt;K,V&gt; hiHead = <span class="keyword">null</span>, hiTail = <span class="keyword">null</span>;</span><br><span class="line">            <span class="keyword">int</span> lc = <span class="number">0</span>, hc = <span class="number">0</span>;</span><br><span class="line">            <span class="keyword">for</span> (TreeNode&lt;K,V&gt; e = b, next; e != <span class="keyword">null</span>; e = next) {</span><br><span class="line">                next = (TreeNode&lt;K,V&gt;)e.next;</span><br><span class="line">                e.next = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">if</span> ((e.hash &amp; bit) == <span class="number">0</span>) {</span><br><span class="line">                    <span class="keyword">if</span> ((e.prev = loTail) == <span class="keyword">null</span>)</span><br><span class="line">                        loHead = e;</span><br><span class="line">                    <span class="keyword">else</span></span><br><span class="line">                        loTail.next = e;</span><br><span class="line">                    loTail = e;</span><br><span class="line">                    ++lc;</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">else</span> {</span><br><span class="line">                    <span class="keyword">if</span> ((e.prev = hiTail) == <span class="keyword">null</span>)</span><br><span class="line">                        hiHead = e;</span><br><span class="line">                    <span class="keyword">else</span></span><br><span class="line">                        hiTail.next = e;</span><br><span class="line">                    hiTail = e;</span><br><span class="line">                    ++hc;</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (loHead != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">if</span> (lc &lt;= UNTREEIFY_THRESHOLD)</span><br><span class="line">                    tab[index] = loHead.untreeify(map);</span><br><span class="line">                <span class="keyword">else</span> {</span><br><span class="line">                    tab[index] = loHead;</span><br><span class="line">                    <span class="keyword">if</span> (hiHead != <span class="keyword">null</span>) <span class="comment">// (else is already treeified)</span></span><br><span class="line">                        loHead.treeify(tab);</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">if</span> (hiHead != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">if</span> (hc &lt;= UNTREEIFY_THRESHOLD)</span><br><span class="line">                    tab[index + bit] = hiHead.untreeify(map);</span><br><span class="line">                <span class="keyword">else</span> {</span><br><span class="line">                    tab[index + bit] = hiHead;</span><br><span class="line">                    <span class="keyword">if</span> (loHead != <span class="keyword">null</span>)</span><br><span class="line">                        hiHead.treeify(tab);</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/* ------------------------------------------------------------ */</span></span><br><span class="line">        <span class="comment">// Red-black tree methods, all adapted from CLR</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">static</span> &lt;K,V&gt; <span class="function">TreeNode&lt;K,V&gt; <span class="title">rotateLeft</span><span class="params">(TreeNode&lt;K,V&gt; root,</span></span></span><br><span class="line"><span class="function"><span class="params">                                              TreeNode&lt;K,V&gt; p)</span> </span>{</span><br><span class="line">            TreeNode&lt;K,V&gt; r, pp, rl;</span><br><span class="line">            <span class="keyword">if</span> (p != <span class="keyword">null</span> &amp;&amp; (r = p.right) != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">if</span> ((rl = p.right = r.left) != <span class="keyword">null</span>)</span><br><span class="line">                    rl.parent = p;</span><br><span class="line">                <span class="keyword">if</span> ((pp = r.parent = p.parent) == <span class="keyword">null</span>)</span><br><span class="line">                    (root = r).red = <span class="keyword">false</span>;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (pp.left == p)</span><br><span class="line">                    pp.left = r;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    pp.right = r;</span><br><span class="line">                r.left = p;</span><br><span class="line">                p.parent = r;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">return</span> root;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="keyword">static</span> &lt;K,V&gt; <span class="function">TreeNode&lt;K,V&gt; <span class="title">rotateRight</span><span class="params">(TreeNode&lt;K,V&gt; root,</span></span></span><br><span class="line"><span class="function"><span class="params">                                               TreeNode&lt;K,V&gt; p)</span> </span>{</span><br><span class="line">            TreeNode&lt;K,V&gt; l, pp, lr;</span><br><span class="line">            <span class="keyword">if</span> (p != <span class="keyword">null</span> &amp;&amp; (l = p.left) != <span class="keyword">null</span>) {</span><br><span class="line">                <span class="keyword">if</span> ((lr = p.left = l.right) != <span class="keyword">null</span>)</span><br><span class="line">                    lr.parent = p;</span><br><span class="line">                <span class="keyword">if</span> ((pp = l.parent = p.parent) == <span class="keyword">null</span>)</span><br><span class="line">                    (root = l).red = <span class="keyword">false</span>;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (pp.right == p)</span><br><span class="line">                    pp.right = l;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    pp.left = l;</span><br><span class="line">                l.right = p;</span><br><span class="line">                p.parent = l;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">return</span> root;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="keyword">static</span> &lt;K,V&gt; <span class="function">TreeNode&lt;K,V&gt; <span class="title">balanceInsertion</span><span class="params">(TreeNode&lt;K,V&gt; root,</span></span></span><br><span class="line"><span class="function"><span class="params">                                                    TreeNode&lt;K,V&gt; x)</span> </span>{</span><br><span class="line">            x.red = <span class="keyword">true</span>;</span><br><span class="line">            <span class="keyword">for</span> (TreeNode&lt;K,V&gt; xp, xpp, xppl, xppr;;) {</span><br><span class="line">                <span class="keyword">if</span> ((xp = x.parent) == <span class="keyword">null</span>) {</span><br><span class="line">                    x.red = <span class="keyword">false</span>;</span><br><span class="line">                    <span class="keyword">return</span> x;</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (!xp.red || (xpp = xp.parent) == <span class="keyword">null</span>)</span><br><span class="line">                    <span class="keyword">return</span> root;</span><br><span class="line">                <span class="keyword">if</span> (xp == (xppl = xpp.left)) {</span><br><span class="line">                    <span class="keyword">if</span> ((xppr = xpp.right) != <span class="keyword">null</span> &amp;&amp; xppr.red) {</span><br><span class="line">                        xppr.red = <span class="keyword">false</span>;</span><br><span class="line">                        xp.red = <span class="keyword">false</span>;</span><br><span class="line">                        xpp.red = <span class="keyword">true</span>;</span><br><span class="line">                        x = xpp;</span><br><span class="line">                    }</span><br><span class="line">                    <span class="keyword">else</span> {</span><br><span class="line">                        <span class="keyword">if</span> (x == xp.right) {</span><br><span class="line">                            root = rotateLeft(root, x = xp);</span><br><span class="line">                            xpp = (xp = x.parent) == <span class="keyword">null</span> ? <span class="keyword">null</span> : xp.parent;</span><br><span class="line">                        }</span><br><span class="line">                        <span class="keyword">if</span> (xp != <span class="keyword">null</span>) {</span><br><span class="line">                            xp.red = <span class="keyword">false</span>;</span><br><span class="line">                            <span class="keyword">if</span> (xpp != <span class="keyword">null</span>) {</span><br><span class="line">                                xpp.red = <span class="keyword">true</span>;</span><br><span class="line">                                root = rotateRight(root, xpp);</span><br><span class="line">                            }</span><br><span class="line">                        }</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">else</span> {</span><br><span class="line">                    <span class="keyword">if</span> (xppl != <span class="keyword">null</span> &amp;&amp; xppl.red) {</span><br><span class="line">                        xppl.red = <span class="keyword">false</span>;</span><br><span class="line">                        xp.red = <span class="keyword">false</span>;</span><br><span class="line">                        xpp.red = <span class="keyword">true</span>;</span><br><span class="line">                        x = xpp;</span><br><span class="line">                    }</span><br><span class="line">                    <span class="keyword">else</span> {</span><br><span class="line">                        <span class="keyword">if</span> (x == xp.left) {</span><br><span class="line">                            root = rotateRight(root, x = xp);</span><br><span class="line">                            xpp = (xp = x.parent) == <span class="keyword">null</span> ? <span class="keyword">null</span> : xp.parent;</span><br><span class="line">                        }</span><br><span class="line">                        <span class="keyword">if</span> (xp != <span class="keyword">null</span>) {</span><br><span class="line">                            xp.red = <span class="keyword">false</span>;</span><br><span class="line">                            <span class="keyword">if</span> (xpp != <span class="keyword">null</span>) {</span><br><span class="line">                                xpp.red = <span class="keyword">true</span>;</span><br><span class="line">                                root = rotateLeft(root, xpp);</span><br><span class="line">                            }</span><br><span class="line">                        }</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="keyword">static</span> &lt;K,V&gt; <span class="function">TreeNode&lt;K,V&gt; <span class="title">balanceDeletion</span><span class="params">(TreeNode&lt;K,V&gt; root,</span></span></span><br><span class="line"><span class="function"><span class="params">                                                   TreeNode&lt;K,V&gt; x)</span> </span>{</span><br><span class="line">            <span class="keyword">for</span> (TreeNode&lt;K,V&gt; xp, xpl, xpr;;)  {</span><br><span class="line">                <span class="keyword">if</span> (x == <span class="keyword">null</span> || x == root)</span><br><span class="line">                    <span class="keyword">return</span> root;</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> ((xp = x.parent) == <span class="keyword">null</span>) {</span><br><span class="line">                    x.red = <span class="keyword">false</span>;</span><br><span class="line">                    <span class="keyword">return</span> x;</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (x.red) {</span><br><span class="line">                    x.red = <span class="keyword">false</span>;</span><br><span class="line">                    <span class="keyword">return</span> root;</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> ((xpl = xp.left) == x) {</span><br><span class="line">                    <span class="keyword">if</span> ((xpr = xp.right) != <span class="keyword">null</span> &amp;&amp; xpr.red) {</span><br><span class="line">                        xpr.red = <span class="keyword">false</span>;</span><br><span class="line">                        xp.red = <span class="keyword">true</span>;</span><br><span class="line">                        root = rotateLeft(root, xp);</span><br><span class="line">                        xpr = (xp = x.parent) == <span class="keyword">null</span> ? <span class="keyword">null</span> : xp.right;</span><br><span class="line">                    }</span><br><span class="line">                    <span class="keyword">if</span> (xpr == <span class="keyword">null</span>)</span><br><span class="line">                        x = xp;</span><br><span class="line">                    <span class="keyword">else</span> {</span><br><span class="line">                        TreeNode&lt;K,V&gt; sl = xpr.left, sr = xpr.right;</span><br><span class="line">                        <span class="keyword">if</span> ((sr == <span class="keyword">null</span> || !sr.red) &amp;&amp;</span><br><span class="line">                            (sl == <span class="keyword">null</span> || !sl.red)) {</span><br><span class="line">                            xpr.red = <span class="keyword">true</span>;</span><br><span class="line">                            x = xp;</span><br><span class="line">                        }</span><br><span class="line">                        <span class="keyword">else</span> {</span><br><span class="line">                            <span class="keyword">if</span> (sr == <span class="keyword">null</span> || !sr.red) {</span><br><span class="line">                                <span class="keyword">if</span> (sl != <span class="keyword">null</span>)</span><br><span class="line">                                    sl.red = <span class="keyword">false</span>;</span><br><span class="line">                                xpr.red = <span class="keyword">true</span>;</span><br><span class="line">                                root = rotateRight(root, xpr);</span><br><span class="line">                                xpr = (xp = x.parent) == <span class="keyword">null</span> ?</span><br><span class="line">                                    <span class="keyword">null</span> : xp.right;</span><br><span class="line">                            }</span><br><span class="line">                            <span class="keyword">if</span> (xpr != <span class="keyword">null</span>) {</span><br><span class="line">                                xpr.red = (xp == <span class="keyword">null</span>) ? <span class="keyword">false</span> : xp.red;</span><br><span class="line">                                <span class="keyword">if</span> ((sr = xpr.right) != <span class="keyword">null</span>)</span><br><span class="line">                                    sr.red = <span class="keyword">false</span>;</span><br><span class="line">                            }</span><br><span class="line">                            <span class="keyword">if</span> (xp != <span class="keyword">null</span>) {</span><br><span class="line">                                xp.red = <span class="keyword">false</span>;</span><br><span class="line">                                root = rotateLeft(root, xp);</span><br><span class="line">                            }</span><br><span class="line">                            x = root;</span><br><span class="line">                        }</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">else</span> { <span class="comment">// symmetric</span></span><br><span class="line">                    <span class="keyword">if</span> (xpl != <span class="keyword">null</span> &amp;&amp; xpl.red) {</span><br><span class="line">                        xpl.red = <span class="keyword">false</span>;</span><br><span class="line">                        xp.red = <span class="keyword">true</span>;</span><br><span class="line">                        root = rotateRight(root, xp);</span><br><span class="line">                        xpl = (xp = x.parent) == <span class="keyword">null</span> ? <span class="keyword">null</span> : xp.left;</span><br><span class="line">                    }</span><br><span class="line">                    <span class="keyword">if</span> (xpl == <span class="keyword">null</span>)</span><br><span class="line">                        x = xp;</span><br><span class="line">                    <span class="keyword">else</span> {</span><br><span class="line">                        TreeNode&lt;K,V&gt; sl = xpl.left, sr = xpl.right;</span><br><span class="line">                        <span class="keyword">if</span> ((sl == <span class="keyword">null</span> || !sl.red) &amp;&amp;</span><br><span class="line">                            (sr == <span class="keyword">null</span> || !sr.red)) {</span><br><span class="line">                            xpl.red = <span class="keyword">true</span>;</span><br><span class="line">                            x = xp;</span><br><span class="line">                        }</span><br><span class="line">                        <span class="keyword">else</span> {</span><br><span class="line">                            <span class="keyword">if</span> (sl == <span class="keyword">null</span> || !sl.red) {</span><br><span class="line">                                <span class="keyword">if</span> (sr != <span class="keyword">null</span>)</span><br><span class="line">                                    sr.red = <span class="keyword">false</span>;</span><br><span class="line">                                xpl.red = <span class="keyword">true</span>;</span><br><span class="line">                                root = rotateLeft(root, xpl);</span><br><span class="line">                                xpl = (xp = x.parent) == <span class="keyword">null</span> ?</span><br><span class="line">                                    <span class="keyword">null</span> : xp.left;</span><br><span class="line">                            }</span><br><span class="line">                            <span class="keyword">if</span> (xpl != <span class="keyword">null</span>) {</span><br><span class="line">                                xpl.red = (xp == <span class="keyword">null</span>) ? <span class="keyword">false</span> : xp.red;</span><br><span class="line">                                <span class="keyword">if</span> ((sl = xpl.left) != <span class="keyword">null</span>)</span><br><span class="line">                                    sl.red = <span class="keyword">false</span>;</span><br><span class="line">                            }</span><br><span class="line">                            <span class="keyword">if</span> (xp != <span class="keyword">null</span>) {</span><br><span class="line">                                xp.red = <span class="keyword">false</span>;</span><br><span class="line">                                root = rotateRight(root, xp);</span><br><span class="line">                            }</span><br><span class="line">                            x = root;</span><br><span class="line">                        }</span><br><span class="line">                    }</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * &#x4E0D;&#x53D8;&#x5F62;&#x9012;&#x5F52;&#x68C0;&#x67E5;</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="keyword">static</span> &lt;K,V&gt; <span class="function"><span class="keyword">boolean</span> <span class="title">checkInvariants</span><span class="params">(TreeNode&lt;K,V&gt; t)</span> </span>{</span><br><span class="line">            TreeNode&lt;K,V&gt; tp = t.parent, tl = t.left, tr = t.right,</span><br><span class="line">                tb = t.prev, tn = (TreeNode&lt;K,V&gt;)t.next;</span><br><span class="line">            <span class="keyword">if</span> (tb != <span class="keyword">null</span> &amp;&amp; tb.next != t)</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">if</span> (tn != <span class="keyword">null</span> &amp;&amp; tn.prev != t)</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">if</span> (tp != <span class="keyword">null</span> &amp;&amp; t != tp.left &amp;&amp; t != tp.right)</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">if</span> (tl != <span class="keyword">null</span> &amp;&amp; (tl.parent != t || tl.hash &gt; t.hash))</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">if</span> (tr != <span class="keyword">null</span> &amp;&amp; (tr.parent != t || tr.hash &lt; t.hash))</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">if</span> (t.red &amp;&amp; tl != <span class="keyword">null</span> &amp;&amp; tl.red &amp;&amp; tr != <span class="keyword">null</span> &amp;&amp; tr.red)</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">if</span> (tl != <span class="keyword">null</span> &amp;&amp; !checkInvariants(tl))</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">if</span> (tr != <span class="keyword">null</span> &amp;&amp; !checkInvariants(tr))</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;介绍&quot;&gt;&lt;a href=&quot;#介绍&quot; class=&quot;headerlink&quot; title=&quot;介绍&quot;&gt;&lt;/a&gt;介绍&lt;/h3&gt;&lt;p&gt;HashMap源代码注释翻译以及代码原理分析。&lt;br&gt;版本：JDK8&lt;/p&gt;
    
    </summary>
    
      <category term="JavaSources" scheme="https://xuqiang.me/categories/JavaSources/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="collections" scheme="https://xuqiang.me/tags/collections/"/>
    
      <category term="hashmap" scheme="https://xuqiang.me/tags/hashmap/"/>
    
  </entry>
  
  <entry>
    <title>一起写个Cache架构【一】——基础缓存</title>
    <link href="https://xuqiang.me/%E4%B8%80%E8%B5%B7%E5%86%99%E4%B8%AACache%E6%9E%B6%E6%9E%84%E3%80%90%E4%B8%80%E3%80%91%E2%80%94%E2%80%94%E5%9F%BA%E7%A1%80%E7%BC%93%E5%AD%98.html"/>
    <id>https://xuqiang.me/一起写个Cache架构【一】——基础缓存.html</id>
    <published>2018-07-09T15:54:36.000Z</published>
    <updated>2018-07-15T16:09:19.000Z</updated>
    
    <content type="html"><![CDATA[<h3 id="&#x5B9E;&#x73B0;&#x76EE;&#x6807;"><a href="#&#x5B9E;&#x73B0;&#x76EE;&#x6807;" class="headerlink" title="&#x5B9E;&#x73B0;&#x76EE;&#x6807;"></a>&#x5B9E;&#x73B0;&#x76EE;&#x6807;</h3><p>&#x57FA;&#x7840;&#x7F13;&#x5B58;&#x5C31;&#x662F;&#x5B9E;&#x73B0;&#x4E00;&#x4E2A;&#x7F13;&#x5B58;&#x8BE5;&#x6709;&#x7684;&#x529F;&#x80FD;&#xFF0C;&#x5728;&#x8FD9;&#x4E2A;&#x7248;&#x672C;&#x4E2D;&#x5148;&#x4E0D;&#x4F1A;&#x8003;&#x8651;&#x6027;&#x80FD;&#x95EE;&#x9898;&#xFF08;&#x6027;&#x80FD;&#x5C06;&#x5728;&#x4E4B;&#x540E;&#x7684;&#x7248;&#x672C;&#x8FDB;&#x884C;&#x4F18;&#x5316;&#xFF09;&#x3002;<br>&#x6211;&#x4EEC;&#x6682;&#x65F6;&#x5B9A;&#x4E49;&#x7684;&#x529F;&#x80FD;&#x6709;&#x5982;&#x4E0B;&#xFF1A;</p><ul><li>&#x5185;&#x5B58;&#x7EA7;&#x7F13;&#x5B58;</li><li>&#x7F13;&#x5B58;&#x8FC7;&#x671F;</li><li>&#x65E0;&#x7F13;&#x5B58;&#x5B58;&#x5728;&#x5219;&#x6839;&#x636E;&#x6570;&#x636E;&#x6E90;&#x81EA;&#x52A8;&#x8F7D;&#x5165;&#x6570;&#x636E;</li></ul><a id="more"></a><h3 id="&#x8BBE;&#x8BA1;&#x601D;&#x8DEF;"><a href="#&#x8BBE;&#x8BA1;&#x601D;&#x8DEF;" class="headerlink" title="&#x8BBE;&#x8BA1;&#x601D;&#x8DEF;"></a>&#x8BBE;&#x8BA1;&#x601D;&#x8DEF;</h3><ol><li>&#x5B9A;&#x4E49;Cache&#x63A5;&#x53E3;</li><li>&#x5B9A;&#x4E49;&#x6570;&#x636E;&#x6E90;&#x52A0;&#x8F7D;&#x8F85;&#x52A9;&#x63A5;&#x53E3;</li><li>&#x5B9A;&#x4E49;&#x5185;&#x5B58;&#x7EA7;&#x7F13;&#x5B58;&#x5B9E;&#x73B0;&#x7C7B;&#xFF0C;&#x5E76;&#x7EC4;&#x5408;&#x7F13;&#x5B58;&#x8FC7;&#x671F;&#x8F85;&#x52A9;&#x7C7B;</li></ol><h3 id="&#x6784;&#x5EFA;&#x9AA8;&#x67B6;"><a href="#&#x6784;&#x5EFA;&#x9AA8;&#x67B6;" class="headerlink" title="&#x6784;&#x5EFA;&#x9AA8;&#x67B6;"></a>&#x6784;&#x5EFA;&#x9AA8;&#x67B6;</h3><p>&#x63A5;&#x4E0B;&#x6765;&#xFF0C;&#x6839;&#x636E;&#x6211;&#x4EEC;&#x7684;&#x601D;&#x8DEF;&#x6784;&#x5EFA;&#x4E00;&#x4E2A;&#x7F13;&#x5B58;&#x67B6;&#x6784;&#x7684;&#x9AA8;&#x67B6;&#x3002;</p><h4 id="&#x6784;&#x5EFA;Cache&#x63A5;&#x53E3;"><a href="#&#x6784;&#x5EFA;Cache&#x63A5;&#x53E3;" class="headerlink" title="&#x6784;&#x5EFA;Cache&#x63A5;&#x53E3;"></a>&#x6784;&#x5EFA;Cache&#x63A5;&#x53E3;</h4><p>&#x7531;&#x4E8E;&#x9700;&#x8981;&#x9488;&#x5BF9;&#x4E0D;&#x540C;&#x7684;&#x5E94;&#x7528;&#x573A;&#x666F;&#xFF0C;&#x6240;&#x4EE5;&#x5BF9;&#x4E8E;&#x4E0D;&#x540C;&#x7684;&#x5E94;&#x7528;&#x573A;&#x666F;&#x9700;&#x8981;&#x6709;&#x4E0D;&#x540C;&#x7684;&#x7F13;&#x5B58;&#x5B9E;&#x4F8B;&#x3002;<br>&#x5728;&#x8FD9;&#x91CC;&#xFF0C;&#x53C2;&#x8003;guava&#x548C;jodd&#x7684;&#x7F13;&#x5B58;&#x5B9E;&#x73B0;&#xFF0C;&#x5B9A;&#x4E49;&#x4E86;&#x4E0D;&#x540C;&#x5BF9;&#x8C61;&#x7C7B;&#x578B;&#x7684;&#x7F13;&#x5B58;&#x5B9E;&#x4F8B;&#x3002;&#x5373;&#x5B9A;&#x4E49;<code>Cache&lt;K, V&gt;</code>&#x6CDB;&#x578B;&#x63A5;&#x53E3;&#x3002;&#x5728;&#x8BE5;&#x63A5;&#x53E3;&#x5185;&#x5305;&#x542B;&#x5982;&#x4E0B;&#x65B9;&#x6CD5;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * &#x52A0;&#x5165;&#x53EF;&#x8FC7;&#x671F;&#x7684;&#x7F13;&#x5B58;</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">put</span><span class="params">(K key, V value, <span class="keyword">long</span> timeout)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * &#x83B7;&#x53D6;&#x7F13;&#x5B58;</span></span><br><span class="line"><span class="comment">  * &#x5982;&#x679C;&#x7F13;&#x5B58;&#x4E0D;&#x5B58;&#x5728;&#xFF0C;&#x5219;&#x901A;&#x8FC7;CacheLoader&#x52A0;&#x8F7D;&#x539F;&#x6570;&#x636E;</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="function">Optional&lt;V&gt; <span class="title">get</span><span class="params">(K key, CacheLoader&lt;V&gt; loader)</span> <span class="keyword">throws</span> InterruptedException, CacheLoaderFailedException</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * &#x5220;&#x9664;&#x7F13;&#x5B58;</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="function"><span class="keyword">boolean</span> <span class="title">remove</span><span class="params">(K key)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * &#x6E05;&#x7406;&#x6240;&#x6709;&#x7F13;&#x5B58;</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="function"><span class="keyword">boolean</span> <span class="title">clearAll</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * &#x83B7;&#x53D6;&#x5DF2;&#x7F13;&#x5B58;&#x7684;&#x6570;&#x91CF;</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">size</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * &#x83B7;&#x53D6;&#x5DF2;&#x7F13;&#x5B58;&#x7684;key&#x96C6;&#x5408;</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="function">Set&lt;K&gt; <span class="title">keys</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * &#x662F;&#x5426;&#x5B58;&#x5728;&#x67D0;&#x4E2A;&#x7F13;&#x5B58;</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="function"><span class="keyword">boolean</span> <span class="title">contains</span><span class="params">(K key)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * &#x7F13;&#x5B58;&#x5FEB;&#x7167;</span></span><br><span class="line"><span class="comment">  * &#x4F1A;&#x6839;&#x636E;&#x6267;&#x884C;&#x65F6;&#x5019;&#x7684;&#x65F6;&#x95F4;&#x70B9;&#xFF0C;&#x62F7;&#x8D1D;&#x4E00;&#x4EFD;&#x7F13;&#x5B58;&#x5185;&#x5BB9;</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line">Map&lt;K, CacheObject&lt;K, V&gt;&gt; snapshot();</span><br></pre></td></tr></tbody></table></figure><p>&#x4E0A;&#x8FF0;&#x57FA;&#x672C;&#x5305;&#x542B;&#x4E86;&#x7F13;&#x5B58;&#x9700;&#x8981;&#x7684;&#x6240;&#x6709;&#x64CD;&#x4F5C;&#xFF0C;&#x6700;&#x91CD;&#x8981;&#x7684;&#x5176;&#x5B9E;&#x5C31;&#x662F;&#x83B7;&#x53D6;&#x4E0E;&#x5B58;&#x5165;&#x8FD9;&#x4E24;&#x4E2A;&#x65B9;&#x6CD5;&#x3002;</p><h3 id="&#x5B9E;&#x73B0;&#x5185;&#x5B58;&#x7EA7;&#x7F13;&#x5B58;"><a href="#&#x5B9E;&#x73B0;&#x5185;&#x5B58;&#x7EA7;&#x7F13;&#x5B58;" class="headerlink" title="&#x5B9E;&#x73B0;&#x5185;&#x5B58;&#x7EA7;&#x7F13;&#x5B58;"></a>&#x5B9E;&#x73B0;&#x5185;&#x5B58;&#x7EA7;&#x7F13;&#x5B58;</h3><p>&#x6839;&#x636E;&#x5B9A;&#x4E49;&#x7684;&#x7F13;&#x5B58;&#x63A5;&#x53E3;&#xFF0C;&#x5C31;&#x53EF;&#x4EE5;&#x5B9E;&#x73B0;&#x5185;&#x5B58;&#x7EA7;&#x7F13;&#x5B58;&#x4E86;&#x3002;</p><p>&#x73B0;&#x5728;&#x6709;&#x4E2A;&#x95EE;&#x9898;&#xFF0C;&#x8BE5;&#x5C06;&#x7F13;&#x5B58;&#x5B58;&#x5165;&#x5230;&#x54EA;&#x79CD;&#x5BB9;&#x5668;&#x5185;&#xFF1F;&#x7B14;&#x8005;&#x5728;&#x8FD9;&#x91CC;&#x662F;&#x901A;&#x8FC7; <code>HashMap</code> &#x6765;&#x5B58;&#x50A8;&#x7F13;&#x5B58;&#x5185;&#x5BB9;&#xFF0C;&#x5E76;&#x901A;&#x8FC7; <code>StampedLock</code>&#x9501; &#x6765;&#x4FDD;&#x8BC1;&#x5E76;&#x53D1;&#x60C5;&#x51B5;&#x4E0B;&#x7684;&#x6570;&#x636E;&#x5171;&#x4EAB;&#x95EE;&#x9898;&#x3002;</p><p>JDK&#x672C;&#x8EAB;&#x5176;&#x5B9E;&#x6709;&#x5E76;&#x53D1;&#x7684;<code>Map</code>&#x96C6;&#x5408;<code>ConcurrentHashMap</code>&#x3002;&#x4E0D;&#x8FC7;&#xFF0C;&#x5728;&#x5B9E;&#x73B0;&#x7F13;&#x5B58;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#x9700;&#x8981;&#x4F7F;&#x7528;&#x5404;&#x79CD;&#x590D;&#x5408;&#x64CD;&#x4F5C;&#xFF0C;&#x800C;&#x5176;&#x672C;&#x8EAB;&#x7684;&#x590D;&#x5408;&#x64CD;&#x4F5C;&#x5E76;&#x4E0D;&#x4E00;&#x5B9A;&#x80FD;&#x591F;&#x5B8C;&#x5168;&#x6EE1;&#x8DB3;&#x4EE5;&#x540E;&#x7684;&#x529F;&#x80FD;&#x6269;&#x5C55;&#xFF08;<code>ConcurrentHashMap</code>&#x65E0;&#x6CD5;&#x5728;&#x5BA2;&#x6237;&#x7AEF;&#x7EA7;&#x522B;&#x52A0;&#x9501;&#x4FDD;&#x8BC1;&#x72EC;&#x5360;&#x5F0F;&#x8BBF;&#x95EE;&#xFF0C;<a href="./Java&#x5E76;&#x53D1;&#x96C6;&#x5408;.html#ConcurrentHashMap">&#x8BE6;&#x7EC6;&#x53EF;&#x4EE5;&#x770B;&#x8FD9;&#x7BC7;&#x6587;&#x7AE0;</a>&#xFF09;&#xFF1B;&#x6240;&#x4EE5;&#xFF0C;&#x76F4;&#x63A5;&#x9009;&#x62E9;&#x4E86;<code>HashMap</code> + <code>StampedLock</code>&#x7684;&#x5F62;&#x5F0F;&#x6765;&#x4FDD;&#x8BC1;&#x591A;&#x7EBF;&#x7A0B;&#x8BBF;&#x95EE;&#xFF0C;&#x8FD9;&#x6837;&#xFF0C;&#x4EE5;&#x540E;&#x5BF9;&#x4E8E;&#x4E00;&#x4E9B;&#x65B0;&#x529F;&#x80FD;&#x6613;&#x4E8E;&#x6269;&#x5C55;&#xFF08;&#x4EE5;&#x540E;&#x53EF;&#x4EE5;&#x8003;&#x8651;&#x53C2;&#x7167;JDK8&#x7684;<code>ConcurrentHashMap</code>&#x76F4;&#x63A5;&#x5B9E;&#x73B0;&#x81EA;&#x5DF1;&#x7684;&#x5BB9;&#x5668;&#xFF0C;&#x4F8B;&#x5982;&#x50CF;guava&#x5C31;&#x662F;&#x53C2;&#x7167;&#x4E86;JDK7&#x7684;<code>ConcurrentHashMap</code>&#x7684;&#x5206;&#x6BB5;&#x9501;&#x539F;&#x7406;&#xFF09;&#x3002;</p><p>&#x786E;&#x5B9A;&#x597D;&#x5BB9;&#x5668;&#x4E4B;&#x540E;&#xFF0C;&#x63A5;&#x4E0B;&#x6765;&#x5C31;&#x8BE5;&#x5B9E;&#x73B0;&#x6211;&#x4EEC;&#x7684;<code>put</code>&#x548C;<code>get</code>&#x65B9;&#x6CD5;&#x4E86;&#x3002;</p><h4 id="put&#x65B9;&#x6CD5;"><a href="#put&#x65B9;&#x6CD5;" class="headerlink" title="put&#x65B9;&#x6CD5;"></a><code>put</code>&#x65B9;&#x6CD5;</h4><p>&#x7531;&#x4E8E;&#x5B58;&#x5165;&#x7F13;&#x5B58;&#x662F;&#x5199;&#x64CD;&#x4F5C;&#xFF0C;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x4FDD;&#x8BC1;&#x5728;&#x5199;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x8BFB;&#x7EBF;&#x7A0B;&#x5904;&#x4E8E;&#x963B;&#x585E;&#x72B6;&#x6001;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x963B;&#x585E;&#x83B7;&#x53D6;&#x5199;&#x9501;</span></span><br><span class="line"><span class="keyword">long</span> stamp = stampedLock.writeLock();</span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line">    <span class="comment">// &#x6839;&#x636E;&#x7F13;&#x5B58;&#x7684;&#x8FC7;&#x671F;&#x65F6;&#x95F4;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x7F13;&#x5B58;&#x5BF9;&#x8C61;</span></span><br><span class="line">    CacheObject&lt;K, V&gt; cacheObject = CacheObject.createValueCache(key, value, timeout);</span><br><span class="line">    <span class="comment">// &#x5C06;&#x7F13;&#x5B58;&#x5BF9;&#x8C61;&#x5B58;&#x5165;&#x5230;&#x7F13;&#x5B58;&#x5BB9;&#x5668;&#x5185;</span></span><br><span class="line">    cacheMap.put(key, cacheObject);</span><br><span class="line">} <span class="keyword">finally</span> {</span><br><span class="line">    <span class="comment">// &#x89E3;&#x9501;&#x5199;&#x9501;</span></span><br><span class="line">    stampedLock.unlockWrite(stamp);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5982;&#x4E0A;&#x4EE3;&#x7801;&#xFF0C;&#x7B14;&#x8005;&#x5728;&#x6267;&#x884C;&#x7F13;&#x5B58;&#x5BF9;&#x8C61;&#x7684;&#x521B;&#x5EFA;&#x4E0E;&#x5B58;&#x5165;&#x4E4B;&#x524D;&#xFF0C;&#x505A;&#x4E86;&#x4E00;&#x6B65;&#x52A0;&#x9501;&#x64CD;&#x4F5C;&#x3002;&#x52A0;&#x9501;&#x64CD;&#x4F5C;&#xFF0C;&#x4E00;&#x4E2A;&#x662F;&#x4E3A;&#x4E86;&#x9632;&#x6B62;<code>HashMap</code>&#x5728;&#x591A;&#x7EBF;&#x7A0B;&#x73AF;&#x5883;&#x4E0B;&#x9020;&#x6210;&#x7684;&#x6B7B;&#x5FAA;&#x73AF;&#x5F02;&#x5E38;&#xFF0C;&#x518D;&#x8005;&#x4E5F;&#x662F;&#x4E3A;&#x4E86;&#x9632;&#x6B62;&#x51FA;&#x73B0;<code>size</code>&#x3001;<code>get</code>&#x8FD9;&#x4E9B;&#x65B9;&#x6CD5;&#x5728;&#x591A;&#x7EBF;&#x7A0B;&#x73AF;&#x5883;&#x4E0B;&#x6570;&#x636E;&#x4E0D;&#x51C6;&#x786E;&#x7684;&#x60C5;&#x51B5;&#xFF0C;&#x800C;&#x8FD9;&#x4E2A;&#x5F88;&#x53EF;&#x80FD;&#x5BFC;&#x81F4;&#x7F13;&#x5B58;&#x51FB;&#x7A7F;&#x7684;&#x4E8B;&#x60C5;&#x53D1;&#x751F;&#xFF0C;&#x8FD9;&#x6837;&#x7F13;&#x5B58;&#x4E5F;&#x5C31;&#x6CA1;&#x6709;&#x610F;&#x4E49;&#x4E86;&#x3002;</p><h4 id="get&#x65B9;&#x6CD5;"><a href="#get&#x65B9;&#x6CD5;" class="headerlink" title="get&#x65B9;&#x6CD5;"></a><code>get</code>&#x65B9;&#x6CD5;</h4><p>&#x6211;&#x4EEC;&#x5728;&#x83B7;&#x53D6;&#x7F13;&#x5B58;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x5982;&#x679C;&#x51FA;&#x73B0;&#x7F13;&#x5B58;&#x4E3A;&#x7A7A;&#x7684;&#x60C5;&#x51B5;&#xFF0C;&#x5219;&#x9700;&#x8981;&#x901A;&#x8FC7;<code>CacheLoader</code>&#x6765;&#x8F85;&#x52A9;&#x83B7;&#x53D6;&#x539F;&#x6570;&#x636E;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5224;&#x65AD;cacheLoader&#x662F;&#x5426;&#x4E3A;&#x7A7A;&#xFF0C;&#x4E3A;&#x7A7A;&#x5219;&#x629B;&#x51FA;&#x975E;&#x6CD5;&#x53C2;&#x6570;&#x5F02;&#x5E38;</span></span><br><span class="line">Asserts.notNull(loader);</span><br><span class="line"><span class="comment">// &#x963B;&#x585E;&#x83B7;&#x53D6;&#x8BFB;&#x9501;&#xFF08;&#x5728;&#x8FD9;&#x91CC;&#x5176;&#x5B9E;&#x53EF;&#x4EE5;&#x4F18;&#x5316;&#x4E3A;&#x4E50;&#x89C2;&#x8BFB;&#xFF0C;&#x7B14;&#x8005;&#x5728;&#x8FD9;&#x91CC;&#x5148;&#x5077;&#x61D2;&#xFF0C;&#x4E4B;&#x540E;&#x5B9E;&#x73B0;&#xFF09;</span></span><br><span class="line"><span class="keyword">long</span> stamp = stampedLock.readLock();</span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line">    <span class="comment">// &#x901A;&#x8FC7;&#x7F13;&#x5B58;&#x5BB9;&#x5668;&#x83B7;&#x53D6;&#x7F13;&#x5B58;</span></span><br><span class="line">    CacheObject&lt;K, V&gt; obj = cacheMap.get(key);</span><br><span class="line">    <span class="comment">// &#x5982;&#x679C;&#x7F13;&#x5B58;&#x4E3A;&#x7A7A;&#x5E76;&#x4E14;cacheLoader&#x662F;&#x4E00;&#x4E2A;&#x7A7A;&#x5B9E;&#x73B0;&#xFF08;&#x5373;&#x6C38;&#x8FDC;&#x8FD4;&#x56DE;&#x7A7A;&#x5BF9;&#x8C61;&#xFF09;&#xFF0C;&#x5219;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x7A7A;&#x5185;&#x5BB9;</span></span><br><span class="line">    <span class="keyword">if</span> (obj == <span class="keyword">null</span> &amp;&amp; loader <span class="keyword">instanceof</span> CacheLoader.EmptyCacheLoader) {</span><br><span class="line">        <span class="keyword">return</span> Optional.empty();</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x5982;&#x679C;&#x7F13;&#x5B58;&#x4E3A;&#x7A7A;</span></span><br><span class="line">    <span class="keyword">if</span> (obj == <span class="keyword">null</span>) {</span><br><span class="line">        <span class="comment">// &#x5C1D;&#x8BD5;&#x9501;&#x5347;&#x7EA7;&#xFF0C;&#x5C06;&#x8BFB;&#x9501;&#x5347;&#x7EA7;&#x5230;&#x5199;&#x9501;&#xFF1B;&#x5728;&#x8FD9;&#x91CC;&#x5C1D;&#x8BD5;CAS&#x81EA;&#x65CB;&#xFF0C;&#x9632;&#x6B62;&#x7EBF;&#x7A0B;&#x72B6;&#x6001;&#x5207;&#x6362;&#x5E26;&#x6765;&#x7684;&#x8D44;&#x6E90;&#x635F;&#x8017;</span></span><br><span class="line">        stamp = stampedLock.tryConvertToWriteLock(stamp);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &#x5224;&#x65AD;&#x9501;&#x5347;&#x7EA7;&#x662F;&#x5426;&#x6210;&#x529F;</span></span><br><span class="line">        <span class="keyword">if</span> (stamp == <span class="number">0L</span>) {</span><br><span class="line">            <span class="comment">// &#x9501;&#x5347;&#x7EA7;&#x5931;&#x8D25;&#xFF0C;&#x963B;&#x585E;&#x83B7;&#x53D6;&#x5199;&#x9501;&#xFF1B;&#x5176;&#x5B9E;&#x8FD9;&#x91CC;&#x4F1A;&#x518D;&#x6B21;&#x5C1D;&#x8BD5;CAS&#x9501;&#x5B9A;&#xFF0C;&#x5982;&#x679C;&#x5931;&#x8D25;&#x52A0;&#x5165;&#x7B49;&#x5F85;&#x961F;&#x5217;&#xFF0C;&#x4E0D;&#x8FC7;&#x8FD9;&#x4E2A;&#x4E0D;&#x5C5E;&#x4E8E;&#x672C;&#x7BC7;&#x6587;&#x7AE0;&#x7684;&#x8303;&#x7574;&#xFF0C;&#x6709;&#x5174;&#x8DA3;&#x7684;&#x540C;&#x5B66;&#x53EF;&#x4EE5;&#x67E5;&#x770B;JDK8&#x7684;StampedLock&#x6E90;&#x7801;</span></span><br><span class="line">            stamp = stampedLock.writeLock();</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x5F02;&#x6B65;&#x4EFB;&#x52A1;</span></span><br><span class="line">        FutureTask&lt;V&gt; futureTask = <span class="keyword">new</span> FutureTask&lt;&gt;(loader::call);</span><br><span class="line">        <span class="comment">// &#x4EE5;&#x5F02;&#x6B65;&#x4EFB;&#x52A1;&#x3001;key&#x4F5C;&#x4E3A;&#x5143;&#x7D20;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x7F13;&#x5B58;&#x5BF9;&#x8C61;</span></span><br><span class="line">        obj = CacheObject.createFutureCache(key, futureTask, <span class="number">0L</span>);</span><br><span class="line">        <span class="comment">// &#x5982;&#x679C;&#x5B58;&#x5728;&#x65E7;&#x7684;&#x7F13;&#x5B58;&#xFF0C;&#x5219;&#x8986;&#x76D6;&#xFF1B;&#x5426;&#x5219;&#x65B0;&#x589E;</span></span><br><span class="line">        cacheMap.replace(key, obj);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x8FD4;&#x56DE;&#x7F13;&#x5B58;&#x5BF9;&#x8C61;&#x5185;&#x7684;&#x7ED3;&#x679C;</span></span><br><span class="line">    <span class="keyword">return</span> obj.getObject();</span><br><span class="line">} <span class="keyword">catch</span> (ExecutionException e) {</span><br><span class="line">    <span class="comment">// &#x6267;&#x884C;&#x5931;&#x8D25;&#x629B;&#x51FA;&#x5F02;&#x5E38;</span></span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> CacheLoaderFailedException(e);</span><br><span class="line">} <span class="keyword">finally</span> {</span><br><span class="line">    <span class="comment">// &#x91CA;&#x653E;&#x9501;&#xFF08;&#x53EF;&#x80FD;&#x662F;&#x5347;&#x7EA7;&#x540E;&#x7684;&#x5199;&#x9501;&#xFF09;</span></span><br><span class="line">    stampedLock.unlock(stamp);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5927;&#x81F4;&#x601D;&#x8DEF;&#x5176;&#x5B9E;&#x662F;&#xFF1A;&#x8BFB;&#x9501;&#x9501;&#x5B9A; -&gt; &#x5982;&#x679C;&#x4E0D;&#x5B58;&#x5728;&#x4E14;&#x65E0;<code>CacheLoader</code>&#x7684;&#x5B9E;&#x73B0;&#x5219;&#x8FD4;&#x56DE;&#x7A7A; -&gt; &#x5982;&#x679C;&#x5B58;&#x5728;&#x5219;&#x8FD4;&#x56DE;&#x5185;&#x5BB9; -&gt; &#x5982;&#x679C;&#x5DF2;&#x7ECF;&#x8FC7;&#x671F;&#x6216;&#x8005;&#x4E0D;&#x5B58;&#x5728;&#x7F13;&#x5B58; -&gt; &#x83B7;&#x53D6;&#x5199;&#x9501; -&gt; &#x91CD;&#x65B0;&#x8F7D;&#x5165;&#x539F;&#x6570;&#x636E; -&gt; &#x91CA;&#x653E;&#x9501;</p><p>&#x81F3;&#x4E8E;&#x5982;&#x679C;&#x901A;&#x8FC7;&#x7F13;&#x5B58;&#x5BF9;&#x8C61;&#x83B7;&#x53D6;&#x7F13;&#x5B58;&#x7684;&#x503C;&#xFF0C;&#x5982;&#x4E0B;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x66F4;&#x65B0;&#x6700;&#x65B0;&#x7684;&#x8BBF;&#x95EE;&#x65F6;&#x95F4;</span></span><br><span class="line">lastAccess = System.currentTimeMillis();</span><br><span class="line"><span class="comment">// &#x8BBF;&#x95EE;&#x6B21;&#x6570;+1</span></span><br><span class="line">accessCount++;</span><br><span class="line"><span class="comment">// &#x5F02;&#x6B65;&#x4EFB;&#x52A1;&#x4E3A;&#x7A7A;&#xFF0C;&#x5219;&#x8FD4;&#x56DE;&#x7F13;&#x5B58;&#x7684;&#x503C;</span></span><br><span class="line"><span class="keyword">if</span> (futureResult == <span class="keyword">null</span>) {</span><br><span class="line">    <span class="keyword">return</span> Optional.ofNullable(result);</span><br><span class="line">}</span><br><span class="line"><span class="comment">// &#x662F;&#x5426;&#x5DF2;&#x7ECF;&#x8BA1;&#x7B97;&#x8FC7;&#x503C;</span></span><br><span class="line"><span class="keyword">if</span> (!futureResult.isDone()) {</span><br><span class="line">    <span class="comment">// &#x672A;&#x8FDB;&#x884C;&#x8FC7;&#x8BA1;&#x7B97;&#xFF0C;&#x6267;&#x884C;&#x5F02;&#x6B65;&#x4EFB;&#x52A1;</span></span><br><span class="line">    futureResult.run();</span><br><span class="line">}</span><br><span class="line"><span class="comment">// &#x963B;&#x585E;&#x83B7;&#x53D6;&#x5F02;&#x6B65;&#x7684;&#x7ED3;&#x679C;</span></span><br><span class="line"><span class="keyword">return</span> Optional.ofNullable(futureResult.get());</span><br></pre></td></tr></tbody></table></figure><h3 id="&#x7F13;&#x5B58;&#x8FC7;&#x671F;"><a href="#&#x7F13;&#x5B58;&#x8FC7;&#x671F;" class="headerlink" title="&#x7F13;&#x5B58;&#x8FC7;&#x671F;"></a>&#x7F13;&#x5B58;&#x8FC7;&#x671F;</h3><p>&#x9488;&#x5BF9;&#x4E8E;&#x7F13;&#x5B58;&#x8FC7;&#x671F;&#x7684;&#x95EE;&#x9898;&#xFF0C;&#x7B14;&#x8005;&#x8FD9;&#x91CC;&#x8BBE;&#x8BA1;&#x4E86;&#x4E24;&#x79CD;&#x5B9E;&#x73B0;&#x65B9;&#x5F0F;&#x3002;</p><ul><li>&#x61D2;&#x8FC7;&#x671F;&#xFF1A;&#x5728;&#x83B7;&#x53D6;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x540C;&#x65F6;&#x5224;&#x65AD;&#x7F13;&#x5B58;&#x662F;&#x5426;&#x5DF2;&#x7ECF;&#x8FC7;&#x671F;&#x3002;&#x4FDD;&#x8BC1;&#x80FD;&#x591F;&#x5B9E;&#x65F6;&#x79FB;&#x9664;&#x8FC7;&#x671F;&#x7F13;&#x5B58;&#x3002;</li><li>&#x5B9A;&#x65F6;&#x6E05;&#x7406;&#xFF1A;&#x542F;&#x52A8;&#x4E00;&#x4E2A;&#x6E05;&#x7406;&#x7EBF;&#x7A0B;&#xFF0C;&#x5BF9;&#x4E8E;&#x5DF2;&#x7ECF;&#x8FC7;&#x671F;&#x7684;&#x7F13;&#x5B58;&#xFF0C;&#x505A;&#x5220;&#x9664;&#x64CD;&#x4F5C;&#xFF0C;&#x9632;&#x6B62;&#x5B58;&#x50A8;&#x7684;&#x5931;&#x6548;&#x7F13;&#x5B58;&#x8FC7;&#x5927;&#x7684;&#x95EE;&#x9898;&#x3002;</li></ul><h4 id="&#x61D2;&#x8FC7;&#x671F;"><a href="#&#x61D2;&#x8FC7;&#x671F;" class="headerlink" title="&#x61D2;&#x8FC7;&#x671F;"></a>&#x61D2;&#x8FC7;&#x671F;</h4><p>&#x61D2;&#x8FC7;&#x671F;&#x7684;&#x673A;&#x5236;&#x5176;&#x5B9E;&#x5F88;&#x597D;&#x5B9E;&#x73B0;&#xFF0C;&#x53EA;&#x8981;&#x5728;&#x83B7;&#x53D6;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x5224;&#x65AD;&#x4E0B;&#x7F13;&#x5B58;&#x5BF9;&#x8C61;&#x662F;&#x5426;&#x8FC7;&#x671F;&#x5373;&#x53EF;&#xFF0C;&#x6211;&#x4EEC;&#x5C06;<code>get</code>&#x65B9;&#x6CD5;&#x66F4;&#x6539;&#x5982;&#x4E0B;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5224;&#x65AD;cacheLoader&#x662F;&#x5426;&#x4E3A;&#x7A7A;&#xFF0C;&#x4E3A;&#x7A7A;&#x5219;&#x629B;&#x51FA;&#x975E;&#x6CD5;&#x53C2;&#x6570;&#x5F02;&#x5E38;</span></span><br><span class="line">Asserts.notNull(loader);</span><br><span class="line"><span class="comment">// &#x963B;&#x585E;&#x83B7;&#x53D6;&#x8BFB;&#x9501;&#xFF08;&#x5728;&#x8FD9;&#x91CC;&#x5176;&#x5B9E;&#x53EF;&#x4EE5;&#x4F18;&#x5316;&#x4E3A;&#x4E50;&#x89C2;&#x8BFB;&#xFF0C;&#x7B14;&#x8005;&#x5728;&#x8FD9;&#x91CC;&#x5148;&#x5077;&#x61D2;&#xFF0C;&#x4E4B;&#x540E;&#x5B9E;&#x73B0;&#xFF09;</span></span><br><span class="line"><span class="keyword">long</span> stamp = stampedLock.readLock();</span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line">    <span class="comment">// &#x901A;&#x8FC7;&#x7F13;&#x5B58;&#x5BB9;&#x5668;&#x83B7;&#x53D6;&#x7F13;&#x5B58;</span></span><br><span class="line">    CacheObject&lt;K, V&gt; obj = cacheMap.get(key);</span><br><span class="line">    <span class="comment">// &#x5982;&#x679C;&#x7F13;&#x5B58;&#x4E3A;&#x7A7A;&#x5E76;&#x4E14;cacheLoader&#x662F;&#x4E00;&#x4E2A;&#x7A7A;&#x5B9E;&#x73B0;&#xFF08;&#x5373;&#x6C38;&#x8FDC;&#x8FD4;&#x56DE;&#x7A7A;&#x5BF9;&#x8C61;&#xFF09;&#xFF0C;&#x5219;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x7A7A;&#x5185;&#x5BB9;</span></span><br><span class="line">    <span class="keyword">if</span> (obj == <span class="keyword">null</span> &amp;&amp; loader <span class="keyword">instanceof</span> CacheLoader.EmptyCacheLoader) {</span><br><span class="line">        <span class="keyword">return</span> Optional.empty();</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x5982;&#x679C;&#x7F13;&#x5B58;&#x4E3A;&#x7A7A;&#x6216;&#x8005;&#x3010;&#x7F13;&#x5B58;&#x8FC7;&#x671F;&#x3011;</span></span><br><span class="line">    <span class="keyword">if</span> (obj == <span class="keyword">null</span> || obj.isExpired()) { &#x2460;</span><br><span class="line">        <span class="comment">// &#x5C1D;&#x8BD5;&#x9501;&#x5347;&#x7EA7;&#xFF0C;&#x5C06;&#x8BFB;&#x9501;&#x5347;&#x7EA7;&#x5230;&#x5199;&#x9501;&#xFF1B;&#x5728;&#x8FD9;&#x91CC;&#x5C1D;&#x8BD5;CAS&#x81EA;&#x65CB;&#xFF0C;&#x9632;&#x6B62;&#x7EBF;&#x7A0B;&#x72B6;&#x6001;&#x5207;&#x6362;&#x5E26;&#x6765;&#x7684;&#x8D44;&#x6E90;&#x635F;&#x8017;</span></span><br><span class="line">        stamp = stampedLock.tryConvertToWriteLock(stamp);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &#x5224;&#x65AD;&#x9501;&#x5347;&#x7EA7;&#x662F;&#x5426;&#x6210;&#x529F;</span></span><br><span class="line">        <span class="keyword">if</span> (stamp == <span class="number">0L</span>) {</span><br><span class="line">            <span class="comment">// &#x9501;&#x5347;&#x7EA7;&#x5931;&#x8D25;&#xFF0C;&#x963B;&#x585E;&#x83B7;&#x53D6;&#x5199;&#x9501;&#xFF1B;&#x5176;&#x5B9E;&#x8FD9;&#x91CC;&#x4F1A;&#x518D;&#x6B21;&#x5C1D;&#x8BD5;CAS&#x9501;&#x5B9A;&#xFF0C;&#x5982;&#x679C;&#x5931;&#x8D25;&#x52A0;&#x5165;&#x7B49;&#x5F85;&#x961F;&#x5217;&#xFF0C;&#x4E0D;&#x8FC7;&#x8FD9;&#x4E2A;&#x4E0D;&#x5C5E;&#x4E8E;&#x672C;&#x7BC7;&#x6587;&#x7AE0;&#x7684;&#x8303;&#x7574;&#xFF0C;&#x6709;&#x5174;&#x8DA3;&#x7684;&#x540C;&#x5B66;&#x53EF;&#x4EE5;&#x67E5;&#x770B;JDK8&#x7684;StampedLock&#x6E90;&#x7801;</span></span><br><span class="line">            stamp = stampedLock.writeLock();</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x5F02;&#x6B65;&#x4EFB;&#x52A1;</span></span><br><span class="line">        FutureTask&lt;V&gt; futureTask = <span class="keyword">new</span> FutureTask&lt;&gt;(loader::call);</span><br><span class="line">        <span class="comment">// &#x4EE5;&#x5F02;&#x6B65;&#x4EFB;&#x52A1;&#x3001;key&#x4F5C;&#x4E3A;&#x5143;&#x7D20;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x7F13;&#x5B58;&#x5BF9;&#x8C61;</span></span><br><span class="line">        obj = CacheObject.createFutureCache(key, futureTask, <span class="number">0L</span>);</span><br><span class="line">        <span class="comment">// &#x5982;&#x679C;&#x5B58;&#x5728;&#x65E7;&#x7684;&#x7F13;&#x5B58;&#xFF0C;&#x5219;&#x8986;&#x76D6;&#xFF1B;&#x5426;&#x5219;&#x65B0;&#x589E;</span></span><br><span class="line">        cacheMap.replace(key, obj);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x8FD4;&#x56DE;&#x7F13;&#x5B58;&#x5BF9;&#x8C61;&#x5185;&#x7684;&#x7ED3;&#x679C;</span></span><br><span class="line">    <span class="keyword">return</span> obj.getObject();</span><br><span class="line">} <span class="keyword">catch</span> (ExecutionException e) {</span><br><span class="line">    <span class="comment">// &#x6267;&#x884C;&#x5931;&#x8D25;&#x629B;&#x51FA;&#x5F02;&#x5E38;</span></span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> CacheLoaderFailedException(e);</span><br><span class="line">} <span class="keyword">finally</span> {</span><br><span class="line">    <span class="comment">// &#x91CA;&#x653E;&#x9501;&#xFF08;&#x53EF;&#x80FD;&#x662F;&#x5347;&#x7EA7;&#x540E;&#x7684;&#x5199;&#x9501;&#xFF09;</span></span><br><span class="line">    stampedLock.unlock(stamp);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>&#x5373;&#x5728; &#x2460; &#x7684;&#x4EE3;&#x7801;&#x5904;&#xFF0C;&#x589E;&#x52A0;&#x4E00;&#x4E2A;&#x6216;&#x5224;&#x65AD;<code>|| obj.isExpired()</code>&#xFF0C;&#x8FD9;&#x4E2A;&#x7684;&#x5224;&#x65AD;&#x903B;&#x8F91;&#x662F;&#x5728;&#x7F13;&#x5B58;&#x5BF9;&#x8C61;&#x5185;&#x5B9E;&#x73B0;&#xFF1A;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// &#x5224;&#x65AD;&#x662F;&#x5426;&#x652F;&#x6301;&#x8FC7;&#x671F;</span></span><br><span class="line"><span class="keyword">if</span> (ttl == <span class="number">0</span>) {</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">}</span><br><span class="line"><span class="comment">// &#x652F;&#x6301;&#x8FC7;&#x671F;&#xFF0C;&#x4E14;&#x4E0A;&#x6B21;&#x8BBF;&#x95EE;&#x52A0;&#x4E0A;&#x8FC7;&#x671F;&#x65F6;&#x95F4;&#x662F;&#x5426;&#x5C0F;&#x4E8E;&#x5F53;&#x524D;&#x7684;&#x65F6;&#x95F4;&#x70B9;&#xFF0C;&#x5982;&#x679C;&#x662F;&#x7684;&#x8BDD;&#xFF0C;&#x5219;&#x4E3A;&#x8FC7;&#x671F;&#x5426;&#x5219;&#x4E3A;&#x6709;&#x6548;&#x7F13;&#x5B58;</span></span><br><span class="line"><span class="keyword">return</span> lastAccess + ttl &lt; System.currentTimeMillis();</span><br></pre></td></tr></tbody></table></figure><h4 id="&#x5B9A;&#x65F6;&#x6E05;&#x7406;"><a href="#&#x5B9A;&#x65F6;&#x6E05;&#x7406;" class="headerlink" title="&#x5B9A;&#x65F6;&#x6E05;&#x7406;"></a>&#x5B9A;&#x65F6;&#x6E05;&#x7406;</h4><p>&#x5B9A;&#x65F6;&#x6E05;&#x7406;&#x7684;&#x673A;&#x5236;&#x7A0D;&#x5FAE;&#x6709;&#x70B9;&#x9EBB;&#x70E6;&#xFF0C;&#x7B14;&#x8005;&#x5728;&#x8FD9;&#x91CC;&#x901A;&#x8FC7;&#x4E00;&#x4E2A;&#x8F85;&#x52A9;&#x7C7B;&#x6765;&#x5B9E;&#x73B0;&#x8FD9;&#x4E2A;&#x673A;&#x5236;&#x3002;</p><p>&#x901A;&#x8FC7;&#x8F85;&#x52A9;&#x7C7B;&#x5B9E;&#x73B0;&#x8FD9;&#x4E2A;&#x673A;&#x5236;&#x7684;&#x539F;&#x56E0;&#x662F;&#xFF1A;&#x5C06;&#x8BE5;&#x6E05;&#x7406;&#x64CD;&#x4F5C;&#x80FD;&#x591F;&#x5E94;&#x7528;&#x4E8E;&#x6240;&#x6709;&#x5B9E;&#x73B0;&#x4E86;Cache&#x63A5;&#x53E3;&#x7684;&#x7F13;&#x5B58;&#x5B9E;&#x4F8B;&#xFF0C;&#x5E76;&#x7531;&#x7F13;&#x5B58;&#x5B9E;&#x73B0;&#x81EA;&#x5DF1;&#x51B3;&#x5B9A;&#x662F;&#x5426;&#x9700;&#x8981;&#x5B9A;&#x65F6;&#x6E05;&#x7406;&#x8FD9;&#x4E2A;&#x673A;&#x5236;&#x3002;</p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">CacheTimeoutHelper</span>&lt;<span class="title">K</span>, <span class="title">V</span>&gt; </span>{</span><br><span class="line"></span><br><span class="line">    <span class="comment">// &#x7F13;&#x5B58;&#x5B9E;&#x4F8B;</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Cache&lt;K, V&gt; cache;</span><br><span class="line">    <span class="comment">// &#x5B9A;&#x671F;&#x95F4;&#x9694;&#x65F6;&#x95F4;</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">long</span> delay;</span><br><span class="line">    <span class="comment">// &#x8FC7;&#x671F;&#x6E05;&#x7406;&#x7EBF;&#x7A0B;&#x6C60;</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> ScheduledExecutorService executor;</span><br><span class="line">    <span class="comment">// &#x662F;&#x5426;&#x5DF2;&#x7ECF;&#x5F00;&#x59CB;&#x6267;&#x884C;&#x6E05;&#x7406;&#x64CD;&#x4F5C;</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">boolean</span> started = <span class="keyword">false</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x5B9E;&#x4F8B;&#x5316;&#x7F13;&#x5B58;&#x6E05;&#x7406;&#x8F85;&#x52A9;&#x7C7B;</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * &#x4F20;&#x5165;&#x7F13;&#x5B58;&#x5B9E;&#x4F8B;&#x4EE5;&#x53CA;&#x5B9A;&#x65F6;&#x6E05;&#x7406;&#x95F4;&#x9694;&#x7684;&#x65F6;&#x95F4;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    CacheTimeoutHelper(Cache&lt;K, V&gt; cache, <span class="keyword">long</span> delay) {</span><br><span class="line">        <span class="keyword">this</span>.cache = cache;</span><br><span class="line">        <span class="keyword">this</span>.delay = delay;</span><br><span class="line">        <span class="comment">// &#x521D;&#x59CB;&#x5316;&#x7EBF;&#x7A0B;&#x6C60;&#xFF0C;&#x5982;&#x679C;&#x6838;&#x5FC3;&#x7EBF;&#x7A0B;&#x6C60;&#x5DF2;&#x6EE1;&#xFF0C;&#x5219;&#x629B;&#x5F03;&#x963B;&#x585E;&#x961F;&#x5217;&#x4E2D;&#x6700;&#x65E9;&#x7684;&#x6267;&#x884C;&#x7EBF;&#x7A0B;</span></span><br><span class="line">        <span class="keyword">this</span>.executor = <span class="keyword">new</span> ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),</span><br><span class="line">            <span class="keyword">new</span> ThreadPoolExecutor.DiscardOldestPolicy());</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">start</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="comment">// &#x8BBE;&#x7F6E;&#x542F;&#x52A8;&#x6807;&#x8BC6;</span></span><br><span class="line">        started = <span class="keyword">true</span>;</span><br><span class="line">        <span class="comment">// &#x7EBF;&#x7A0B;&#x8C03;&#x5EA6;</span></span><br><span class="line">        executor.schedule(() -&gt; {</span><br><span class="line">            <span class="comment">// &#x53EA;&#x9700;&#x8981;&#x904D;&#x5386;&#x7F13;&#x5B58;&#xFF0C;&#x505A;&#x4E00;&#x6B21;get&#x64CD;&#x4F5C;&#xFF0C;&#x4F1A;&#x81EA;&#x52A8;&#x5C06;&#x8FC7;&#x671F;&#x7F13;&#x5B58;&#x5220;&#x9664;&#xFF08;&#x53EF;&#x80FD;&#x5B58;&#x5728;bug&#xFF09;</span></span><br><span class="line">            <span class="keyword">for</span> (K key : cache.keys()) {</span><br><span class="line">                <span class="keyword">try</span> {</span><br><span class="line">                    Optional&lt;V&gt; value = cache.get(key);</span><br><span class="line">                    <span class="comment">// &#x5982;&#x679C;&#x503C;&#x6CA1;&#x6709;&#x627E;&#x5230;&#xFF0C;&#x5219;&#x76F4;&#x63A5;&#x79FB;&#x9664;&#xFF0C;&#x4E0D;&#x7BA1;&#x5B58;&#x4E0D;&#x5B58;&#x5728;&#xFF08;&#x53EF;&#x80FD;&#x6709;&#x503C;&#x4E0D;&#x5B58;&#x5728;&#xFF0C;&#x4F46;&#x662F;key&#x5B58;&#x5728;&#x7684;&#x60C5;&#x51B5;&#xFF09;</span></span><br><span class="line">                    <span class="keyword">if</span> (!value.isPresent()) {</span><br><span class="line">                        cache.remove(key);</span><br><span class="line">                    }</span><br><span class="line">                } <span class="keyword">catch</span> (InterruptedException e) {</span><br><span class="line">                    Thread.currentThread().interrupt();</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }, delay, TimeUnit.SECONDS);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * &#x662F;&#x5426;&#x5DF2;&#x7ECF;&#x542F;&#x52A8;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isStarted</span><span class="params">()</span> </span>{</span><br><span class="line">        <span class="keyword">return</span> started;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="&#x603B;&#x7ED3;"><a href="#&#x603B;&#x7ED3;" class="headerlink" title="&#x603B;&#x7ED3;"></a>&#x603B;&#x7ED3;</h3><p>&#x603B;&#x4F53;&#x5B9E;&#x73B0;&#x4E86;&#x7F13;&#x5B58;&#x7684;&#x57FA;&#x672C;&#x529F;&#x80FD;&#xFF0C;&#x53EF;&#x80FD;&#x5728;&#x6027;&#x80FD;&#x4E0A;&#x4EE5;&#x53CA;&#x4EE3;&#x7801;&#x903B;&#x8F91;&#x4E0A;&#x5B58;&#x5728;&#x4E00;&#x4E9B;&#x53EF;&#x4F18;&#x5316;&#x7684;&#x5730;&#x65B9;&#xFF0C;&#x540E;&#x671F;&#x5C06;&#x4F1A;&#x6162;&#x6162;&#x8C03;&#x6574;&#x4F18;&#x5316;&#x3002;</p><p>&#x4EE5;&#x4E0B;&#x662F;Github&#x7684;&#x4ED3;&#x5E93;&#x5730;&#x5740;&#xFF1A;<br><a href="https://github.com/LightweightJava/cache" target="_blank" rel="noopener">https://github.com/LightweightJava/cache</a></p><p>&#x6B22;&#x8FCE;&#x5404;&#x4F4D;&#x7ED9;star&#x6216;&#x8005;&#x548C;&#x8D21;&#x732E;&#x4EE3;&#x7801;&#x3002;</p><p><strong>&#x4E00;&#x8D77;&#x5199;&#x4E2A;Cache&#x67B6;&#x6784;</strong><br><a href="./&#x4E00;&#x8D77;&#x5199;&#x4E2A;Cache&#x67B6;&#x6784;&#x3010;&#x96F6;&#x3011;&#x2014;&#x2014;&#x5206;&#x6790;&#x4E0E;&#x8BA1;&#x5212;.html">&#x5206;&#x6790;&#x4E0E;&#x8BA1;&#x5212;</a><br><a href="./&#x4E00;&#x8D77;&#x5199;&#x4E2A;Cache&#x67B6;&#x6784;&#x3010;&#x4E00;&#x3011;&#x2014;&#x2014;&#x57FA;&#x7840;&#x7F13;&#x5B58;.html">&#x57FA;&#x7840;&#x7F13;&#x5B58;</a></p><script>        document.querySelectorAll('.github-emoji')          .forEach(el => {            if (!el.dataset.src) { return; }            const img = document.createElement('img');            img.style = 'display:none !important;';            img.src = el.dataset.src;            img.addEventListener('error', () => {              img.remove();              el.style.color = 'inherit';              el.style.backgroundImage = 'none';              el.style.background = 'none';            });            img.addEventListener('load', () => {              img.remove();            });            document.body.appendChild(img);          });      </script>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;实现目标&quot;&gt;&lt;a href=&quot;#实现目标&quot; class=&quot;headerlink&quot; title=&quot;实现目标&quot;&gt;&lt;/a&gt;实现目标&lt;/h3&gt;&lt;p&gt;基础缓存就是实现一个缓存该有的功能，在这个版本中先不会考虑性能问题（性能将在之后的版本进行优化）。&lt;br&gt;我们暂时定义的功能有如下：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;内存级缓存&lt;/li&gt;&lt;li&gt;缓存过期&lt;/li&gt;&lt;li&gt;无缓存存在则根据数据源自动载入数据&lt;/li&gt;&lt;/ul&gt;
    
    </summary>
    
      <category term="Java" scheme="https://xuqiang.me/categories/Java/"/>
    
      <category term="Concurrent" scheme="https://xuqiang.me/categories/Java/Concurrent/"/>
    
      <category term="Cache" scheme="https://xuqiang.me/categories/Java/Concurrent/Cache/"/>
    
    
      <category term="java" scheme="https://xuqiang.me/tags/java/"/>
    
      <category term="concurrent" scheme="https://xuqiang.me/tags/concurrent/"/>
    
      <category term="cache" scheme="https://xuqiang.me/tags/cache/"/>
    
      <category term="lock" scheme="https://xuqiang.me/tags/lock/"/>
    
      <category term="readwritelock" scheme="https://xuqiang.me/tags/readwritelock/"/>
    
  </entry>
  
</feed>
