<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>archive</title><link>https://archive-w.netlify.app/doc/framework/mybatis/</link><description>Recent content on archive</description><generator>Hugo</generator><language>zh-CN</language><atom:link href="https://archive-w.netlify.app/doc/framework/mybatis/index.xml" rel="self" type="application/rss+xml"/><item><title/><link>https://archive-w.netlify.app/doc/framework/mybatis/mybatis/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/doc/framework/mybatis/mybatis/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="intromybatis--underlying">
 Intro(MyBatis | underlying)
 &lt;a class="anchor" href="#intromybatis--underlying">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>
&lt;h3 id="要点">
 要点
 &lt;a class="anchor" href="#%e8%a6%81%e7%82%b9">#&lt;/a>
&lt;/h3>
&lt;div class="alert callout attention">&lt;p class="title">&lt;span class="icon icon-attention">&lt;/span> Attention &lt;/p>&lt;p> 1. mapper 接口定义的语句怎么生成的? configuration解析后会生成一个 MappedStatement{id:&amp;quot;&amp;quot;}. 并且将ID 和 ms 放入 configuration 中的 mappedStatements 中。
&lt;br>2. 执行顺序是什么样的？
&lt;br>3. 缓存是如何处理的？
&lt;br>4. 拦截器原理。&lt;/p>
&lt;/p>&lt;/div>
&lt;/li>
&lt;li>
&lt;h3 id="mapper接口的实现">
 Mapper接口的实现
 &lt;a class="anchor" href="#mapper%e6%8e%a5%e5%8f%a3%e7%9a%84%e5%ae%9e%e7%8e%b0">#&lt;/a>
&lt;/h3>
&lt;p class="warn">通过&lt;code>MapperRegistry&lt;/code>里面的 map 类型的 knowMappers 根据 type 获取到 MapperProxyFactory ,进而调用&lt;code>return mapperProxyFactory.newInstance(sqlSession);&lt;/code>返回一个 mapper 接口代理对象。
&lt;br> 上述代理对象中使用的 InvocationHandler 叫 &lt;code>MapperProxy&lt;/code>，里面 invoke() 的实现是将方法包装成一个&lt;code>MapperMethod&lt;/code> mm 存放在&lt;code>MapperMethodInvoker&lt;/code> mmi 里面，并会进行缓存，然后调用 mmi 里面的 invoke，进而执行到 mm.execute()方法，内部通过执行器拿到结果返回。&lt;/p>
&lt;/li>
&lt;li>
&lt;h3 id="拦截器实现">
 拦截器实现
 &lt;a class="anchor" href="#%e6%8b%a6%e6%88%aa%e5%99%a8%e5%ae%9e%e7%8e%b0">#&lt;/a>
&lt;/h3>
&lt;p class="warn">


 &lt;a href="https://mybatis.org/mybatis-3/zh_CN/configuration.html#plugins" rel="noopener" target="_blank">插件文档&lt;/a>
&lt;br>&lt;br>对于拦截器来说，主要在以下接口工作：&lt;code>Executor&lt;/code>，&lt;code>ParameterHandler&lt;/code>，&lt;code>ResultSetHandler&lt;/code>，&lt;code>StatementHandler&lt;/code>。
&lt;br>&lt;br>涉及的主要类有，实现了 


 
 

 
 
 
 
 
 
 
 
 
 &lt;a href='https://archive-w.netlify.app/doc/advance/#jdk' rel="noopener" class="internal-link" data-src="https://archive-w.netlify.app/doc/advance/#jdk">JDK 代理&lt;/a> 中 &lt;strong>InvocationHandler&lt;/strong> 的 &lt;code>Plugin&lt;/code>，以及 &lt;code>Interceptor&lt;/code>接口。
&lt;br>&lt;br>大致调用流程：
&lt;br>&lt;code>1.&lt;/code> 创建对象：&lt;code>executor = new CachingExecutor(executor);&lt;/code>
&lt;br>&lt;code>2.&lt;/code> 将所有拦截器进行插件化：&lt;code>executor = (Executor) interceptorChain.pluginAll(executor);&lt;/code>内部实现如下：
&lt;br>&lt;span style='padding-left:2em'>&lt;code>2.1.&lt;/code> 在 &lt;strong>Plugin&lt;/strong> 代码中第 13 行，将 executor 对象，以及拦截器对象进行包装。如果拦截器注解签名方法中需要拦截的类在目标对象上的话，返回代理对象。如果不是，则返回target就行。
&lt;br>&lt;span style='padding-left:2em'>&lt;code>2.2.&lt;/code> 返回的代理对象是实现了目标对象上面的接口，此处也就是 executor，所以可以强转。
&lt;br>&lt;span style='padding-left:2em'>&lt;code>2.3.&lt;/code> 因为在 &lt;strong>InterceptorChain&lt;/strong> 第六行循环中，需要注意第一次循环后返回的target可能是代理对象，下一次循环中可能返回代理对象 &lt;em>去代理&lt;/em> 代理对象的情况。如下图：
&lt;br>&lt;span style='padding-left:5em'> &lt;img src="https://archive-w.netlify.app/.images/doc/framework/mybatis/underlying/u-interceptor-01.png" alt="" width="70%">
&lt;br>&lt;br>&lt;code>3.&lt;/code> 使用对象：内部的执行流程可以画图表示，涉及 JDK 代理。
&lt;br>&lt;span style='padding-left:2em'>如果在外部调用刚才插件化的代理对象的话，则首先调用到 &lt;strong>invoke()&lt;/strong> 方法中，然后根据签名map 判断是否当前方法是拦截器需要拦截的方法，根据判断结果选择是进入拦截器拦截方法 &lt;strong>intercept(Invocation invocation)&lt;/strong>，还是直接调用目标对象（此处的目标对象有可能是还是一个代理对象）。
&lt;br>&lt;span style='padding-left:5em'> &lt;img src="https://archive-w.netlify.app/.images/doc/framework/mybatis/underlying/u-interceptor-02.png" alt="" width="80%">&lt;/p></description></item></channel></rss>