小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Mybatis源碼分析(四):屬性接口之configLocation

 云夢(mèng)天涯rqxe9h 2018-02-14

上節(jié)內(nèi)容我們了解了SqlSessionFactoryBean所有暴露出來(lái)的屬性,方便用戶通過(guò)配置對(duì)mybatis擴(kuò)展!今天我們一起看看configLocation源碼!

 

對(duì)configLocation進(jìn)行源碼分析我就的知道這個(gè)屬性在spring和mybatis整合的時(shí)候怎么使用!

一.configLocation如何使用

Spring核心配置文件中的配置如下(SqlSessionFactoryBean配置configLocation屬性,去加載mybatis的config配置文件

'sqlSessionFactory' class='org.mybatis.spring.SqlSessionFactoryBean'>
   property name='dataSource' ref='dataSource' />
   
   property name='configLocation'>
     value>classpath:sqlMapConfig.xmlvalue>
   property>
bean>


sqlMapConfig.xml

<>xml version='1.0' encoding='UTF-8' ?>  
PUBLIC '-////DTD Config 3.0//EN'  
'http:///dtd/mybatis-3-config.dtd'>
 
configuration>  
 typeAliases>
    typeAlias type='com.zzy.model.User' alias='User' />
 typeAliases>
 mappers>
    mapper resource='com/zzy/xml/UserMapper.xml' />
 mappers>
 
configuration>


這里標(biāo)簽屬性實(shí)際上和上節(jié)SqlSessionFactoryBean  下屬性是一致的。暫時(shí)不做詳細(xì)配置?。ㄒ簿褪强梢园裇qlSessionFactoryBean下屬性全部配置到mybatis配置文件中)


二.源碼分析過(guò)程

1.configLocation 的入口源碼


先看這個(gè)屬性被mybatis讀取位置的源碼


SqlSessionFactoryBean  >> buildSqlSessionFactory

XMLConfigBuilder xmlConfigBuilder = null;
   if (this.configuration != null) {
     configuration = this.configuration;
     if (configuration.getVariables() == null) {
       configuration.setVariables(this.configurationProperties);
     } else if (this.configurationProperties != null) {
       configuration.getVariables().putAll(this.configurationProperties);
     }
   } else if (this.configLocation != null) {
     xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
     configuration = xmlConfigBuilder.getConfiguration();
   } else {
     if (LOGGER.isDebugEnabled()) {
       LOGGER.debug('Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration');
     }
     configuration = new Configuration();
     if (this.configurationProperties != null) {
       configuration.setVariables(this.configurationProperties);
     }
   }


上述代碼含義Mybatis初始化的過(guò)程,首先看configuration是否為空,初始化之前這個(gè)對(duì)象是為空的。


然后就是看是否配置了configLocation 。


如果配置了,會(huì)將configLocation包裝成一個(gè)xmlConfigBuilder對(duì)象。


有必要先說(shuō)明下org.apache.ibatis.session.Configuration

和org.apache.ibatis.builder.xml.XMLConfigBuilder這兩個(gè)類

 

Configuration:

mybatis的一個(gè)數(shù)據(jù)管家,里面存在了,只要mybatis執(zhí)行過(guò)程中用到的各種數(shù)據(jù)都在,例如:mapper文件路徑、別名數(shù)據(jù)、解析出來(lái)的sql語(yǔ)句、結(jié)果集數(shù)據(jù)等)這個(gè)類在mybatis框架中比較總要的一個(gè)類,下期著重講!

 

XMLConfigBuilder:

public class XMLConfigBuilder extends BaseBuilder

用來(lái)解析mybatis的全局配置文件sqlMapConfig.xml的,這個(gè)類繼承自父類BaseBuilder,父類中有個(gè)很重要的方法parse(代碼如下:

else if (this.configLocation != null) {
     xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
     configuration = xmlConfigBuilder.getConfiguration();
   }


2.xmlConfigBuilder 解析sqlMapConfig.xml過(guò)程


a.

上面sqlMapConfig.xml被讀取到后,創(chuàng)建了xmlConfigBuilder對(duì)象,然后是用xmlConfigBuilder中的方法解析xml文件,繼續(xù)看buildSqlSessionFactory這個(gè)方法。xml解析的位置在這個(gè)方法中靠下的位置有如下代碼:


if (xmlConfigBuilder != null) {
     try {
       xmlConfigBuilder.parse();

       if (LOGGER.isDebugEnabled()) {
         LOGGER.debug('Parsed configuration file: '' + this.configLocation + ''');
       }
     } catch (Exception ex) {
       throw new NestedIOException('Failed to parse config resource: ' + this.configLocation, ex);
     } finally {
       ErrorContext.instance().reset();
     }
   }


xmlConfigBuilder.parse();就是解析讀取到的mybatis配置文件

sqlMapConfig.xml。


b.

XmlConfigBuilder 的parse方法源碼:


public Configuration parse() {
   if (parsed) {
     throw new BuilderException('Each XMLConfigBuilder can only be used once.');
   }
   parsed = true;
   parseConfiguration(parser.evalNode('/configuration'));
   return configuration;
 }

其中parseConfiguration(parser.evalNode('/configuration'));

這段代碼簡(jiǎn)單說(shuō)下,parseConfiguration深入解析的方法。

 

parser.evalNode('/configuration')屬于XPath 語(yǔ)法【自己復(fù)習(xí)】,這個(gè)地方的含義就是選取configuration為根節(jié)點(diǎn),我們可以看到

parser.evalNode('/configuration')返回值是

sqlMapConfig.xml文件中configuration就是根節(jié)點(diǎn),獲取到

configuration根節(jié)點(diǎn)的全部信息,斷點(diǎn)截圖如下:

c.

parseConfiguration() 源碼如下:

private void parseConfiguration(XNode root) {
   try {
     //issue #117 read properties first
     propertiesElement(root.evalNode('properties'));
     Properties settings = settingsAsProperties(root.evalNode('settings'));
     loadCustomVfs(settings);
     typeAliasesElement(root.evalNode('typeAliases'));
     pluginElement(root.evalNode('plugins'));
     objectFactoryElement(root.evalNode('objectFactory'));
     objectWrapperFactoryElement(root.evalNode('objectWrapperFactory'));
     reflectorFactoryElement(root.evalNode('reflectorFactory'));
     settingsElement(settings);
     // read it after objectFactory and objectWrapperFactory issue #631
     environmentsElement(root.evalNode('environments'));
     databaseIdProviderElement(root.evalNode('databaseIdProvider'));
     typeHandlerElement(root.evalNode('typeHandlers'));
     mapperElement(root.evalNode('mappers'));
   } catch (Exception e) {
     throw new BuilderException('Error parsing SQL Mapper Configuration. Cause: ' + e, e);
   }
 }


上面代碼就是對(duì)sqlMapConfig.xml文件中的標(biāo)簽依次讀取(就是上節(jié)講到的mybatis所暴露出的所有接口)Mybatis源碼分析(三):Mybatis所有暴露的接口及其作用


舉兩個(gè)元素解讀的例子:xml文件中兩個(gè)標(biāo)簽(typeAliasesmappers)的解析方法

  typeAliasesElement(root.evalNode('typeAliases'));

  mapperElement(root.evalNode('mappers'));

 

簡(jiǎn)單說(shuō)明下typeAliases標(biāo)簽的解析過(guò)程,除去mappers標(biāo)簽之外,其他標(biāo)簽就不做詳細(xì)解讀(類似typeAliases)。

typeAliases標(biāo)簽的解析過(guò)程源碼如下:


private void typeAliasesElement(XNode parent) {
   if (parent != null) {
     for (XNode child : parent.getChildren()) {
       if ('package'.equals(child.getName())) {
         String typeAliasPackage = child.getStringAttribute('name');
         configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
       } else {
         String alias = child.getStringAttribute('alias');
         String type = child.getStringAttribute('type');
         try {
           Class clazz = Resources.classForName(type);
           if (alias == null) {
             typeAliasRegistry.registerAlias(clazz);
           } else {
             typeAliasRegistry.registerAlias(alias, clazz);
           }
         } catch (ClassNotFoundException e) {
           throw new BuilderException('Error registering typeAlias for '' + alias + ''. Cause: ' + e, e);
         }
       }
     }
   }
 }


上面整個(gè)過(guò)程就是對(duì)typeAlias type='com.zzy.model.User' alias='User' />解析的過(guò)程

上面代碼中我們可以看到一個(gè)對(duì)象typeAliasRegistry,這個(gè)對(duì)象反射類是

TypeAliasRegistry,這個(gè)類是用來(lái)包裝別名存在的map

 

簡(jiǎn)單看看TypeAliasRegistry.class:

public class TypeAliasRegistry {

 private final MapString, Class> TYPE_ALIASES = new HashMapString, Class>();



其中TYPE_ALIASES存放別名對(duì)應(yīng)關(guān)系的一個(gè)map,這個(gè)map又被typeAliasRegistry封裝。

 

上面代碼typeAliasRegistry.registerAlias(alias, clazz)就是講type和alias的對(duì)應(yīng)關(guān)系注冊(cè)到typeAliasRegistry對(duì)象的map中!

 

以上所有的操作過(guò)程都在XMLConfigBuilder中,在XMLConfigBuilder父類BaseBuilder中有這樣一段代碼

this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();


最后typeAliasRegistry 別名對(duì)象還是被放到大數(shù)據(jù)管家configuration中了(下節(jié)分析configuration),驗(yàn)證了我們上面說(shuō)的configuration包含mybatis所需的各種數(shù)據(jù)。


d.

 mapperElement(root.evalNode('mappers'))源碼中截取重要的一段


if (resource != null && url == null && mapperClass == null) {
           ErrorContext.instance().resource(resource);
           InputStream inputStream = Resources.getResourceAsStream(resource);
           XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
           mapperParser.parse();
         }



關(guān)鍵方法 mapperParser.parse()代碼:

public void parse() {
   if (!configuration.isResourceLoaded(resource)) {
     configurationElement(parser.evalNode('/mapper'));
     configuration.addLoadedResource(resource);
     bindMapperForNamespace();
   }

   parsePendingResultMaps();
   parsePendingChacheRefs();
   parsePendingStatements();
 }


這個(gè)方法是對(duì)Mapper.xml文件中增刪改查標(biāo)簽解析的過(guò)程。


多說(shuō)一句,通過(guò)mapperLocation這個(gè)屬性配置Mapper.xml文件,解析Mapper.xml也會(huì)回到上面方法中(后期分析mapperLocation屬性接口的

時(shí)候會(huì)通過(guò)源碼看到)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多