1. 程式人生 > >Mybatis 原始碼解析三、Mapper介面與mapper.xml檔案繫結

Mybatis 原始碼解析三、Mapper介面與mapper.xml檔案繫結

     一、流程圖介紹整體過程
              1、首先根據MapperScannerConfigurer進行包掃描,掃描Mapper介面,生成Spring特定的描述,並將其交由MapperProxyFactory管理,後期會由其生成動態代理物件。
              ClassOathMapperScanner 中的doScan()方法。                 
  1. GenericBeanDefinition definition =(GenericBeanDefinition) holder.getBeanDefinition();
  2. if(logger.isDebugEnabled())
    {
  3. logger.debug("Creating MapperFactoryBean with name '"+ holder.getBeanName()
  4. +"' and '"+ definition.getBeanClassName()+"' mapperInterface");
  5. }
  6. // the mapper interface is the original class of the bean
  7. // but, the actual class of the bean is MapperFactoryBean
  8. definition.getPropertyValues().add
    ("mapperInterface", definition.getBeanClassName());
  9. definition.setBeanClass(MapperFactoryBean.class);
  10. definition.getPropertyValues().add("addToConfig",this.addToConfig);

    2、初始化SqlSessionFactoryBean。首先判定mybatis.xml中的mapper屬性是否配置如果配置,解析Mapper介面新增到Configuration中。
            XMLConfigBuilder中的mapperElement()方法             
  1. private
    void mapperElement(XNode parent)throwsException{
  2. if(parent !=null){
  3. for(XNode child : parent.getChildren()){
  4. if("package".equals(child.getName())){
  5. String mapperPackage = child.getStringAttribute("name");
  6. configuration.addMappers(mapperPackage);
  7. }else{
  8. String resource = child.getStringAttribute("resource");
  9. String url = child.getStringAttribute("url");
  10. String mapperClass = child.getStringAttribute("class");
  11. if(resource !=null&& url ==null&& mapperClass ==null){
  12. ErrorContext.instance().resource(resource);
  13. InputStream inputStream =Resources.getResourceAsStream(resource);
  14. XMLMapperBuilder mapperParser =newXMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
  15. mapperParser.parse();
  16. }elseif(resource ==null&& url !=null&& mapperClass ==null){
  17. ErrorContext.instance().resource(url);
  18. InputStream inputStream =Resources.getUrlAsStream(url);
  19. XMLMapperBuilder mapperParser =newXMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
  20. mapperParser.parse();
  21. }elseif(resource ==null&& url ==null&& mapperClass !=null){
  22. Class<?> mapperInterface =Resources.classForName(mapperClass);
  23. configuration.addMapper(mapperInterface);
  24. }else{
  25. thrownewBuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
  26. }
  27. }
  28. }
  29. }
  30. }

    3、判定SqlSessionFactoryBean節點中是否配置mapperLocations屬性,也即mapper.xml檔案所在位置。會根據mapper.xml檔案中配置的名稱空間,獲取Mapper介面,並新增到Configuration中。
        XMLMapperBuilder中的bindMapperForNamespace()方法。         
  1. privatevoid bindMapperForNamespace(){
  2. String namespace = builderAssistant.getCurrentNamespace();
  3. if(namespace !=null){
  4. Class<?> boundType =null;
  5. try{
  6. boundType =Resources.classForName(namespace);
  7. }catch(ClassNotFoundException e){
  8. //ignore, bound type is not required
  9. }
  10. if(boundType !=null){
  11. if(!configuration.hasMapper(boundType)){
  12. // Spring may not know the real resource name so we set a flag
  13. // to prevent loading again this resource from the mapper interface
  14. // look at MapperAnnotationBuilder#loadXmlResource
  15. configuration.addLoadedResource("namespace:"+ namespace);
  16. configuration.addMapper(boundType);
  17. }
  18. }
  19. }
  20. }

    4、如果以上都沒有配置,需要使用Mapper的代理物件時,就會使用包掃描獲得的Mapper介面資訊,解析Mapper介面,新增到Configuration中。     5、Configuration新增Mapper介面過程。
        MapperRegistry總的addMapper()方法
        
  1. public<T>void addMapper(Class<T> type){
  2. if(type.isInterface()){
  3. if(hasMapper(type)){
  4. thrownewBindingException("Type "+ type +" is already known to the MapperRegistry.");
  5. }
  6. boolean loadCompleted =false;
  7. try{
  8. knownMappers.put(type,newMapperProxyFactory<T>(type));
  9. // It's important that the type is added before the parser is run
  10. // otherwise the binding may automatically be attempted by the
  11. // mapper parser. If the type is already known, it won't try.
  12. MapperAnnotationBuilder parser =newMapperAnnotationBuilder(config, type);
  13. parser.parse();
  14. loadCompleted =true;
  15. }finally{
  16. if(!loadCompleted){
  17. knownMappers.remove(type);
  18. }
  19. }
  20. }
  21. }

    5.1 根據介面資訊獲取mapper.xml檔案,校驗mapper.xml檔案配置是否正確
        MapperAnnotationBuilder中的parse()方法
        
  1. publicvoid parse(){
  2. String resource = type.toString();
  3. if(!configuration.isResourceLoaded(resource)){
  4. loadXmlResource();
  5. configuration.addLoadedResource(resource);
  6. assistant.setCurrentNamespace(type.getName());
  7. parseCache();
  8. parseCacheRef();
  9. Method[] methods = type.getMethods();
  10. for(Method method : methods){
  11. try{
  12. if(!method.isBridge()){// issue #237
  13. parseStatement(method);
  14. }
  15. }catch(IncompleteElementException e){
  16. configuration.addIncompleteMethod(newMethodResolver(this, method));
  17. }
  18. }
  19. }
  20. parsePendingMethods();
  21. }
     MapperAnnotationBuilder中的loadXmlResource()方法
  1. privatevoid loadXmlResource(){
  2. // Spring may not know the real resource name so we check a flag
  3. // to prevent loading again a resource twice
  4. // this flag is set at XMLMapperBuilder#bindMapperForNamespace
  5. if(!configuration.isResourceLoaded("namespace:"+ type.getName()))

    相關推薦

    Mybatis 原始碼解析Mapper介面mapper.xml檔案

         一、流程圖介紹整體過程               1、首先根據MapperScannerConfigurer進行包掃描,掃描Mapper介面,生成Spring特定的描述,並將其交

    Mybatis 原始碼解析Mapper介面的代理實現過程 MapperScannerConfigurer 解析

    一、使用包掃描的配置方式生成Mapper的動態代理物件 上一篇文章中介紹了SqlSessionFactoryBean 通過Mybatis主配置檔案生成Mapper介面的代理物件,並將其儲存到Configuration中,但是一般在開發中我們並不是採用這種方式配置Ma

    Mybatis 原始碼解析()

    文章個人學習原始碼所得,若存在不足或者錯誤之處,請大家指出。 Properties配置格式如下: Configuration.xml中: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE

    mybatis原始碼解析()-SqlSession.selectOne類似方法呼叫過程

    上篇部落格中介紹了mybatis的載入過程,這篇部落格介紹一下org.apache.ibatis.session.SqlSession的增、刪、改、查方法是怎麼實現的。我們使用mybatis時,基本都是使用Mapper進行增、刪、改、查操作,但是SqlS

    mybatis原始碼-二.DefaultSqlSession動態代理介面例項Mapper

    DefaultSqlSession@Override public <T> T getMapper(Class<T> type) { return configuration.<T>getMapper(type, t

    精盡MyBatis原始碼分析 - MyBatis初始化(二)之載入 Mapper 介面 XML 對映檔案

    > 該系列文件是本人在學習 Mybatis 的原始碼過程中總結下來的,可能對讀者不太友好,請結合我的原始碼註釋([Mybatis原始碼分析 GitHub 地址](https://github.com/liu844869663/mybatis-3)、[Mybatis-Spring 原始碼分析 GitHub 地址

    mybatis原始碼-解析配置檔案)之配置檔案Configuration解析(超詳細, 值得收藏)

    1. 簡介 1.1 系列內容 本系列文章講解的是mybatis解析配置檔案內部的邏輯, 即 Reader reader = Resources.getResourceAsReader("mybatis-config.xml"); SqlSessionFact

    mybatis原始碼-解析配置檔案(四)之配置檔案Mapper解析

    其中, mappers作為configuration節點的一部分配置, 在本文章中, 我們講解解析mappers節點, 即 xxxMapper.xml 檔案的解析。 1 解析入口 在解析 mybatis-config.xml 時, 會進行解析 xxxMapper.xml 的檔案。 在圖示流程的 XMLCo

    mybatis原始碼-解析配置檔案(四-1)之配置檔案Mapper解析(cache)

    1. 簡介 本文章主要講解的是, xxxMapper.xml 檔案中, cache 節點的原始碼。 2. 解析 XMLMapperBuilder.cacheElement() 方法主要負責解析 <cache> private void cacheElement(XNode context)

    Eclipse使用Mybatis Generator生成pojo物件mapper介面mapper.xml檔案

    下載外掛: 第一步:下載mybatis.generator外掛 org.mybatis.generator.eclipse.site-1.3.5.201609070108.zip,下載地址:https://github.com/mybatis/generator/relea

    MyBatis原始碼解析)——Transaction事務模組(轉)

    1、回顧   之前介紹了Environment環境類,這其實是一個單例類,在MyBatis執行開啟後只會存在一個唯一的環境例項,雖然我們可以在Configuration配置檔案中配置多個環境,但是專案執行中只會存在其中的一個,一般專案會存在開發環境和測試環境、生產環境三

    Mybatis mapper介面xml檔案路徑分離

    為什麼分離   對於Maven專案,IntelliJ IDEA預設是不處理src/main/java中的非java檔

    Spring Boot系列():Spring Boot整合Mybatis原始碼解析

    一、Mybatis回顧   1、MyBatis介紹   Mybatis是一個半ORM框架,它使用簡單的 XML 或註解用於配置和原始對映,將介面和Java的POJOs(普通的Java 物件)對映成資料庫中的記錄。   2、Mybatis整體架構  二、Spring Boot整合Mybatis +

    負載均衡web服務集群搭建

    spa 編譯安裝 特點 ont tables 1.7 常用 標準 靜態 一、負載均衡LVS基本介紹 LB集群的架構和原理很簡單,就是當用戶的請求過來時,會直接分發到Director Server上,然後它把用戶的請求根據設置好的調度算法,智能均衡地分發到後端真正服務器

    原始碼解析--Longlong型別的比較遇到的問題

    Long、long型別的比較遇到的問題: 1、long 是基本型別 Long是物件型別。 public static void main(String[] args) { Long A = 127l; Long B = 127l; long C = 127; l

    Spring原始碼解析 - 一環境搭建

    環境搭建 1.  安裝git: https://desktop.github.com/         安裝git以及使用教程: https://blog.csdn.net/qq_39705793/article/deta

    Netty伺服器多客戶連線利用廣播方式完全理解netty的讀寫機制

             本篇採用的編解碼是netty自帶的字串的格式的編解碼,使用者1可以控制檯發訊息(輸入完訊息要加換行符號,是一個訊息結束的分隔符,後面我會在編解碼中詳細講解)給伺服器,伺服器廣播給其他所有的客戶端,這個機制,我們遊戲開發伺服器中應

    Elastic-Job原始碼解析()之分片定時任務執行

    通過本篇的閱讀你將學會了解Elastic-Job的定時時機,及如何通過分片方式做一個分散式的定時任務框架。瞭解常用的三種分片策略,及如何自定義分散式分片策略 目錄 Elastic-Job如何通過SpringJobScheduler啟動定時 Ela

    MyBatis原始碼解析之日誌記錄

    一 .概述 MyBatis沒有提供日誌的實現類,需要接入第三方的日誌元件,但第三方日誌元件都有各自的Log級別,且各不相同,但MyBatis統一提供了trace、debug、warn、error四個級別; 自動掃描日誌實現,並且第三方日誌外掛載入優先順序如下:slf4J → commonsLoging →

    【學習轉載】MyBatis原始碼解析——日誌記錄

    宣告:轉載自前輩:開心的魚a1 一 .概述 MyBatis沒有提供日誌的實現類,需要接入第三方的日誌元件,但第三方日誌元件都有各自的Log級別,且各不相同,但MyBatis統一提供了trace、debug、warn、error四個級別; 自動掃描日誌實現,並且第三方日誌外掛載入優先順序如下:sl