首頁  >  文章  >  Java  >  深入淺出Mybatis系列(六)---objectFactory、plugins、mappers簡介與配置

深入淺出Mybatis系列(六)---objectFactory、plugins、mappers簡介與配置

黄舟
黄舟原創
2017-03-02 10:50:151461瀏覽

上篇文章《深入淺出Mybatis系列(五)---TypeHandler簡介及配置(mybatis源碼篇)》簡單看了一下TypeHandler, 本次將結束對於mybatis的設定檔的學習, 本次涉及到剩下沒提及到的幾個節點的配置:objectFactory、databaseIdProvider、plugins、mappers。

那麼,接下來,就簡單介紹一下這幾個配置的作用吧:

1、objectFactory是做什麼的? 需要配置嗎?

  MyBatis 每次建立結果物件的新實例時,它都會使用一個物件工廠(ObjectFactory)實例來完成。預設的物件工廠需要做的只是實例化目標類,要麼透過預設建構方法,要麼在參數映射存在的時候透過參數建構方法來實例化。預設情況下,我們不需要配置,mybatis會呼叫預設實作的objectFactory。 除非我們要自訂ObjectFactory的實現, 那我們才需要去手動配置。

  那麼怎麼自訂實作ObjectFactory? 怎麼配置呢?

  自訂ObjectFactory只需要去繼承DefaultObjectFactory(是ObjectFactory介面的實作類別),並重寫其方法即可。具體的,本處不多說,後面再具體講解。

  寫好了ObjectFactory, 只需做如下設定: 


<configuration>
    ......    <objectFactory type="org.mybatis.example.ExampleObjectFactory">
        <property name="someProperty" value="100"/>
    </objectFactory>
    ......  </configuration


2、plugin有何作用? 需要配置嗎?

  plugins 是一個可選設定。 mybatis中的plugin其實就是個interceptor, 它可以攔截Executor 、ParameterHandler 、ResultSetHandler 、StatementHandler 的部分方法,處理我們自己的邏輯。 Executor就是真正執行sql語句的東西, ParameterHandler 是處理我們傳入參數的,還記得前面講TypeHandler的時候提到過,mybatis預設幫我們實作了不少的typeHandler, 當我們不顯示配置typeHandler的時候,mybatis會根據參數類型自動選擇適合的typeHandler執行,其實就是ParameterHandler 在選擇。 ResultSetHandler 就是處理回傳結果的。

   怎麼自訂plugin ? 怎麼設定?

   要自訂一個plugin, 需要去實作Interceptor接口, 這兒不細說, 後面實戰部分會詳細講解。定義好之後,配置如下:

<configuration>
    ......    <plugins>
      <plugin interceptor="org.mybatis.example.ExamplePlugin">
        <property name="someProperty" value="100"/>
      </plugin>
    </plugins>
    ......  </configuration>

3、mappers, 這下引出mybatis的核心之一了,mappers作用 ? 需要配置嗎?

  mappers 節點下,配置我們的mapper映射文件, 所謂的mapper映射文件,就是讓mybatis 用來建立資料表和javabean映射的一個橋樑。在我們實際開發中,通常一個mapper檔對應一個dao接口, 這個mapper可以看做是dao的實作。所以,mappers必須配置。

  那麼怎麼配置呢?

<configuration>
    ......    <mappers>
      <!-- 第一种方式:通过resource指定 -->
    <mapper resource="com/dy/dao/userDao.xml"/>
    
     <!-- 第二种方式, 通过class指定接口,进而将接口与对应的xml文件形成映射关系
             不过,使用这种方式必须保证 接口与mapper文件同名(不区分大小写), 
             我这儿接口是UserDao,那么意味着mapper文件为UserDao.xml 
     <mapper class="com.dy.dao.UserDao"/>      -->
      
      <!-- 第三种方式,直接指定包,自动扫描,与方法二同理 
      <package name="com.dy.dao"/>      -->
      <!-- 第四种方式:通过url指定mapper文件位置
      <mapper url="file://........"/>       -->
  </mappers>
    ......  </configuration>

本篇僅作簡單介紹, 更高級的使用以及其實現原理,會在後面的實戰部分進行詳細講解。

這幾個節點的解析源碼,與之前提到的那些節點的解析類似,故此處不再講。 我將原始碼折疊, 需要的可以打開看看。

/**
 * objectFactory 节点解析 
 */private void objectFactoryElement(XNode context) throws Exception {    
 if (context != null) {      
 //读取type属性的值, 接下来进行实例化ObjectFactory, 并set进 configuration      
 //到此,简单讲一下configuration这个对象,其实它里面主要保存的都是mybatis的配置
      String type = context.getStringAttribute("type");      
      //读取propertie的值, 根据需要可以配置, mybatis默认实现的objectFactory没有使用properties
      Properties properties = context.getChildrenAsProperties();
      
      ObjectFactory factory = (ObjectFactory) resolveClass(type).newInstance();
      factory.setProperties(properties);
      configuration.setObjectFactory(factory);
    }
 } 
  
  /**
   * plugins 节点解析   */
  private void pluginElement(XNode parent) throws Exception {    if (parent != null) {      for (XNode child : parent.getChildren()) {
        String interceptor = child.getStringAttribute("interceptor");
        Properties properties = child.getChildrenAsProperties();        //由此可见,我们在定义一个interceptor的时候,需要去实现Interceptor, 这儿先不具体讲,以后会详细讲解
        Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
        interceptorInstance.setProperties(properties);
        configuration.addInterceptor(interceptorInstance);
      }
    }
  }  
  /**
   * mappers 节点解析
   * 这是mybatis的核心之一,这儿先简单介绍,在接下来的文章会对它进行分析   */
  private void mapperElement(XNode parent) throws Exception {    if (parent != null) {      for (XNode child : parent.getChildren()) {        if ("package".equals(child.getName())) {          //如果mappers节点的子节点是package, 那么就扫描package下的文件, 注入进configuration
          String mapperPackage = child.getStringAttribute("name");
          configuration.addMappers(mapperPackage);
        } else {
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");          //resource, url, class 三选一
          
          if (resource != null && url == null && mapperClass == null) {
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);            //mapper映射文件都是通过XMLMapperBuilder解析
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url != null && mapperClass == null) {
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url == null && mapperClass != null) {
            Class<?> mapperInterface = Resources.classForName(mapperClass);
            configuration.addMapper(mapperInterface);
          } else {            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
          }
        }
      }
    }
  }

本次就简单的到此结束, 从下篇文章开始,将会开始接触到mybatis的核心部分,不过首先还是要讲mapper文件的配置及使用, 并通过源码进一步深入核心。

 以上就是深入浅出Mybatis系列(六)---objectFactory、plugins、mappers简介与配置的内容,更多相关内容请关注PHP中文网(www.php.cn)!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn