亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MyBatis插件原理是什么

發布時間:2021-10-21 15:16:45 來源:億速云 閱讀:168 作者:iii 欄目:開發技術

本篇內容主要講解“MyBatis插件原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“MyBatis插件原理是什么”吧!

如何集成分頁插件

Spring-Boot+Mybatis+PageHelper 。

引入pom依賴

<dependency>    <groupId>com.github.pagehelper</groupId>    <artifactId>pagehelper-spring-boot-starter</artifactId>    <version>1.2.3</version> </dependency>

配置分頁插件配置項

pagehelper:   helperDialect: mysql   reasonable: true   supportMethodsArguments: true   params: count=countSql

service接口代碼中

PageInfo selectUsersByName(int pageIndex, int pageSize);

service實現類代碼中

@Override public PageInfo selectUsersByName(int pageIndex, int pageSize) {     PageHelper.startPage(pageIndex, pageSize);     List<User> users = userMapper.selectUsersByName(null);     return new PageInfo(users); }

Mapper代碼代碼

<select id="selectUsersByName" resultMap="User">     select * from m_user     <where>         <if test="userName != null and userName != ''">             `name` = #{userName}         </if>     </where> </select>
List<User> selectUsersByName(@Param("userName") String userName);

controller中代碼

@GetMapping("/user/name") public PageInfo selectUsersByName(int pageIndex, int pageSize) {     return userService.selectUsersByName(pageIndex, pageSize); }

然后我們訪問

http://localhost:9002/user/name?pageIndex=1&pageSize=10

輸出結果:

MyBatis插件原理是什么

輸出重要項說明:

  • pageNum:當前頁碼。

  • pageSize:每頁數。

  • list:就是我們返回的業務數據。

  • total:總數據。

  • hasNextPage:是否存在下一頁。

我們在看看輸出SQL:

MyBatis插件原理是什么

發現其實執行了兩條SQL:count和limit。

猜測分頁插件實現

1.這個分頁插件無非就是在我們的查詢條件上拼接了個limit和做了一個count查詢。

2.我們這里使用的是Mysql作為數據庫,如果是Oracle的話那就不是limit了,所以這里有多重數據庫對應的方案。

3.在沒有此插件的前面攔截并做了sql和相關處理。

根據官網快速入門插件

下面是來自官網的一段話:

MyBatis 允許你在映射語句執行過程中的某一點進行攔截調用。默認情況下,MyBatis 允許使用插件來攔截的方法調用包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction,  close, isClosed)

  • ParameterHandler (getParameterObject, setParameters)

  • ResultSetHandler (handleResultSets, handleOutputParameters)

  • StatementHandler (prepare, parameterize, batch, update, query)

這些類中方法的細節可以通過查看每個方法的簽名來發現,或者直接查看 MyBatis  發行包中的源代碼。如果你想做的不僅僅是監控方法的調用,那么你最好相當了解要重寫的方法的行為。因為在試圖修改或重寫已有方法的行為時,很可能會破壞 MyBatis  的核心模塊。這些都是更底層的類和方法,所以使用插件的時候要特別當心。

通過 MyBatis 提供的強大機制,使用插件是非常簡單的,只需實現 Interceptor 接口,并指定想要攔截的方法簽名即可。

那我們就嘗試著按照官方來寫一個插件。

自定義插件

@Intercepts({@Signature(         type= Executor.class,         method = "update",         args = {MappedStatement.class,Object.class})}) public class TianPlugin implements Interceptor {     private Properties properties = new Properties();      @Override     public Object intercept(Invocation invocation) throws Throwable {         System.out.println("老田寫的一個Mybatis插件--start");         Object returnObject = invocation.proceed();         System.out.println("老田寫的一個Mybatis插件---end");         return returnObject;     } }

然后把插件類注入到容器中。

MyBatis插件原理是什么

這里的自定義完全是官網給出的案例。從自定義的插件類中看到有個update,我們猜測肯定是需要執行update才會被攔截到。

訪問前面的代碼:http://localhost:9002/updateUser

MyBatis插件原理是什么

成功了。

這是大家肯定會聯想到我們剛剛開始學動態代理的時候,不就是在要調用的方法的前面和后面做點小東東嗎?

Mybatis的插件確實就是這樣的。

我們來分析一下官方的那段話和我們自定義的插件。

分析

首先,我們自定義的插件必須是針對下面這四個類以及方法。

  • Executor (update, query, flushStatements, commit, rollback, getTransaction,  close, isClosed)

  • ParameterHandler (getParameterObject, setParameters)

  • ResultSetHandler (handleResultSets, handleOutputParameters)

  • StatementHandler (prepare, parameterize, batch, update, query)

其次,我們必須實現Mybatis的Interceptor。

MyBatis插件原理是什么

Interceptor中三個方法的作用:

  • intercept():執行攔截內容的地方,比如:在調用某類方法前后做一些自己的處理,簡單就是打印日志。

  • plugin():決定是否觸發intercept()方法。

  • setProperties():給自定義的攔截器傳遞我們配置的屬性參數(這個可以暫時不管他,后面我們寫一個相對完整點的插件,你就明白是干啥的了)。

plugin方法

default Object plugin(Object target) {     return Plugin.wrap(target, this);   }

默認實現方法,里面調用了Plugin.wrap()方法。

public class Plugin implements InvocationHandler {    private Object target;   private Interceptor interceptor;   private Map<Class<?>, Set<Method>> signatureMap;    private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {     this.target = target;     this.interceptor = interceptor;     this.signatureMap = signatureMap;   }    public static Object wrap(Object target, Interceptor interceptor) {     Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);     Class<?> type = target.getClass();     Class<?>[] interfaces = getAllInterfaces(type, signatureMap);     if (interfaces.length > 0) {       // 創建JDK動態代理對象       return Proxy.newProxyInstance(           type.getClassLoader(),           interfaces,           new Plugin(target, interceptor, signatureMap));     }     return target;   }    @Override   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {     try {       Set<Method> methods = signatureMap.get(method.getDeclaringClass());       // 判斷是否是需要攔截的方法(很重要)       if (methods != null && methods.contains(method)) {         // 回調intercept()方法         return interceptor.intercept(new Invocation(target, method, args));       }       return method.invoke(target, args);     } catch (Exception e) {       throw ExceptionUtil.unwrapThrowable(e);     }   } //...省略其他不相關代碼 }

這不就是一個JDK動態代理嗎?

Map

所以,我們不要動不動就說反射性能很差,那是因為你沒有像Mybatis一樣去緩存一個對象的反射結果。

判斷是否是需要攔截的方法,這句注釋很重要,一旦忽略了,都不知道Mybatis是怎么判斷是否執行攔截內容的,要記住。

Plugin.wrap(target, this)是干什么的?

使用JDK的動態代理,給target對象創建一個delegate代理對象,以此來實現方法攔截和增強功能,它會回調intercept()方法。

為什么要寫注解?注解都是什么含義?

在我們自定義的插件上有一堆注解,別害怕。

Mybatis規定插件必須編寫Annotation注解,是必須,而不是可選。

@Intercepts({@Signature( type= Executor.class, method = "update",                         args = {MappedStatement.class,Object.class})}            ) public class TianPlugin implements Interceptor {

@Intercepts注解:裝載一個@Signature列表,一個@Signature其實就是一個需要攔截的方法封裝。那么,一個攔截器要攔截多個方法,自然就是一個@Signature列表。

type= Executor.class, method = "update",args = {MappedStatement.class,Object.class}

解釋:要攔截Executor接口內的query()方法,參數類型為args列表。

MyBatis插件原理是什么

那如果想攔截多個方法呢?

@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Intercepts {   Signature[] value(); }

這就簡單了吧,我們在@Intercepts注解中可以存放多個@Signature注解。

比如說前面分頁插件中就是攔截多個方法的。

MyBatis插件原理是什么

為什么攔截兩個都是query方法呢?因為在Executor中有兩個query方法。

MyBatis插件原理是什么

到此,相信大家對“MyBatis插件原理是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西乌珠穆沁旗| 乳山市| 平远县| 五常市| 夏河县| 宝丰县| 新余市| 江西省| 化州市| 蕉岭县| 承德县| 台湾省| 兴安县| 赤城县| 永善县| 丰县| 财经| 宁河县| 林周县| 白河县| 芒康县| 兰坪| 江山市| 江门市| 呼图壁县| 嘉峪关市| 临高县| 兴安县| 奉新县| 新昌县| 韶山市| 汤阴县| 烟台市| 黔江区| 祁连县| 泾源县| 湘潭市| 朝阳市| 资中县| 油尖旺区| 武夷山市|