溫馨提示×

溫馨提示×

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

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

mybatis的插件機制示例詳解

發布時間:2020-09-01 13:13:29 來源:腳本之家 閱讀:207 作者:山東大蔥哥 欄目:編程語言

前言

Mybatis作為一個應用廣泛的優秀的ORM框架,已經成了JavaWeb世界近乎標配的部分,這個框架具有強大的靈活性,在四大組件(Executor、StatementHandler、ParameterHandler、ResultSetHandler)處提供了簡單易用的插件擴展機制。Mybatis對持久層的操作就是借助于四大核心對象。MyBatis支持用插件對四大核心對象進行攔截,對mybatis來說插件就是攔截器,用來增強核心對象的功能,增強功能本質上是借助于底層的動態代理實現的,換句話說,MyBatis中的四大對象都是代理對象。

四大核心對象簡介

MyBatis 四大核心對象

ParameterHandler:處理SQL的參數對象

ResultSetHandler:處理SQL的返回結果集

StatementHandler:數據庫的處理對象,用于執行SQL語句

Executor:MyBatis的執行器,用于執行增刪改查操作

Mybatis插件原理

  1. Mybatis的插件借助于責任鏈的模式進行對攔截的處理
  2. 使用動態代理對目標對象進行包裝,達到攔截的目的
  3. 作用于Mybatis的作用域對象之上

攔截

插件具體是如何攔截并附加額外的功能的呢?

以ParameterHandler 來說

 public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object object, BoundSql sql, InterceptorChain interceptorChain){
 ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement,object,sql);
 parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
 return parameterHandler;
 }
public Object pluginAll(Object target) {
 for (Interceptor interceptor : interceptors) {
 target = interceptor.plugin(target);
 }
 return target;
 }

interceptorChain 保存了所有的攔截器(interceptors),是mybatis初始化的時候創建的。調用攔截器鏈中的攔截器依次的對目標進行攔截或增強。interceptor.plugin(target)中的target就可以理解為mybatis中的四大對象。返回的target是被重重代理后的對象。

插件接口

Mybatis插件接口-Interceptor

1.Intercept方法,插件的核心方法

2.plugin方法,生成target的代理對象

3.setProperties方法,傳遞插件所需參數

插件實例

插件開發需要以下步驟

  1. 自定義插件需要實現上述接口
  2. 增加@Intercepts注解(聲明是哪個核心組件的插件,以及對哪些方法進行擴展)
  3. 在xml文件中配置插件
/** 插件簽名,告訴mybatis單錢插件用來攔截那個對象的哪個方法 **/
@Intercepts({@Signature(type = ResultSetHandler.class,method ="handleResultSets",args = Statement.class)})
public class MyFirstInterceptor implements Interceptor {

 /** @Description 攔截目標對象的目標方法 **/
 @Override
 public Object intercept(Invocation invocation) throws Throwable {
 System.out.println("攔截的目標對象:"+invocation.getTarget());
 Object object = invocation.proceed();
 return object;
 }
 /**
 * @Description 包裝目標對象 為目標對象創建代理對象
 * @Param target為要攔截的對象
 * @Return 代理對象
 */
 @Override
 public Object plugin(Object target) {
 System.out.println("將要包裝的目標對象:"+target);
 return Plugin.wrap(target,this);
 }
 /** 獲取配置文件的屬性 **/
 @Override
 public void setProperties(Properties properties) {
 System.out.println("插件配置的初始化參數:"+properties);
 }
}

在mybatis.xml中配置插件

<!-- 自定義插件 -->
 <plugins>
  <plugin interceptor="mybatis.interceptor.MyFirstInterceptor">
   <!--配置參數-->
   <property name="name" value="Bob"/>
  </plugin>
 </plugins>

調用查詢方法,查詢方法會返回ResultSet

public class MyBatisTest {
 public static SqlSessionFactory sqlSessionFactory = null;

 public static SqlSessionFactory getSqlSessionFactory() {
  if (sqlSessionFactory == null) {
   String resource = "mybatis-config.xml";
   try {
    Reader reader = Resources.getResourceAsReader(resource);
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
  return sqlSessionFactory;
 }

 public void testGetById()
 {
  SqlSession sqlSession = this.getSqlSessionFactory().openSession();
  PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
  Person person=personMapper.getById(2001);
  System.out.println(person.toString());
 }

public static void main(String[] args) {
  new MyBatisTest().testGetById();
 }
}

輸出結果

插件配置的初始化參數:{name=Bob}
將要包裝的目標對象:org.apache.ibatis.executor.CachingExecutor@754ba872
將要包裝的目標對象:org.apache.ibatis.scripting.defaults.DefaultParameterHandler@192b07fd
將要包裝的目標對象:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@7e0b0338
將要包裝的目標對象:org.apache.ibatis.executor.statement.RoutingStatementHandler@1e127982
攔截的目標對象:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@7e0b0338
Person{id=2001, username='Tom', email='email@0', gender='F'}

多插件開發過程

1.創建代理對象時,按照插件配置的順序進行包裝

2.執行目標方法后,是按照代理的逆向進行執行

總結

1.遵循插件盡量不使用的原則,因為會修改底層設計
2.插件是生成的層層代理對象的責任鏈模式,使用反射機制實現
3.插件的編寫要考慮全面,特別是多個插件層層代理的時候

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。

向AI問一下細節

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

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女