mybatis之XML解析源码分析

来源:互联网 发布:淘宝香港高登iphone 编辑:程序博客网 时间:2024/06/05 07:22

一直想知道mybatis是如何解析xml文件的,今天认真看了下源码,这里记录一下

这里是用mybatis-springSqlSessionFactoryBean当作的入口,mybatis-spring其实很简单,源码也就几个看看就懂了,代理了一下而已没啥东东.

1.解析spring的配置

不过很多参数都是spring中来处理了,所以mybatis-spring没有先parse而是先加载了配置文件

依次是

  1. typeAliasesPackage
  2. typeAliases
  3. Plugins
  4. typeHandlersPackage
  5. typeHandlers

typeAliases

相当于加载了上面的typeAliases,plugins,typeHandlers

然后typeAliases putTYPE_ALIASES供查询时调用类型转换

Plugins

拦截器也private final List<Interceptor> interceptors = new ArrayList<Interceptor>();

这里用的ArrayList所以是自顶向下按照顺序执行的

typeHandlers

Typehandler 也是putprivate final Map<Class<?>, Map<JdbcType, TypeHandler>> TYPE_HANDLER_MAP = new

HashMap<Class<?>, Map<JdbcType, TypeHandler>>();到时候使用

 

2.解析我们自己配置的configLocation.xml

计算机生成了可选文字:if (xm1ConfigBui1de ! null) { try { IConf1gBu11de .parse if (this.logger 、 .1sDebugEnab1ed()) { this.logger 、 debug("Par 、 sed confIgu ratlon flle } catch (Exceptlon (x) { + this.conf1gLocat10n + + this.conf1gLocat10n ex) throw new NestedIOExcept10n("Fa11ed to pa pse confIg re s ou pc e } finally { ., 、 eset(); . 1 ' IS 亡 口 ' Ice

 

解析的内容,内容和前面已经后面雷同这里就不多说了

计算机生成了可选文字:private void at 、 seConfigur 、 atlon (XNode , 、 00t ) { try { typeA11asesE1ement 、 00t . evalNode( "typeA11ases , plug1nE1ement 、 00t . evalNode( " pluglns , obJectFactoryE1ement(r 、 00t . evalNode( " objectFactopy ' ) ) , (b) ectWr 、 apper 、 FactoryE1ement (root . evalNode ( " (b) ectWpappepFactopy ' ) ) , 、 opert1esE1ement (root . evalNode ( " properties , sett1ngsE1ement(r 、 00t . evalNode( " settlngs " ) ) ; env1ronmentsE1ement (root . evalNode( " envlponments " ) ) , typeHand1er 、 Element (root . evalNode ( "typeHand1eps " 、 Element 、 00t . evalNode( " mappe ' } catch (Exceptlon e) { throw new Bullder 、 Except10n("Err 、 0, 、 papslng SQL Mapper 、 Conflgur 、 atlon . Cause

3.生成环境变量,貌似作用不大-因为都被spring接管了哈

计算机生成了可选文字:new Env1t 、 onment(thxs.envlt 、 onment, this.tr 、 ansact10nFactory, this.dataSource 、 atIOn . ,

4.解析sql文件!重点来了

计算机生成了可选文字:new XMLMapper 、 Bullder 、 (mapper 、 Locatlon .getlnputstr 、 eam( XMLMapper 、 Bullder 、 xm1Mapper 、 Bullder 、 conflguratlon, path , conflgur 、 atlon .getSq1Fr 、 agments()), xm1Mapper 、 Bullder 、 . parse

依次是命名空间,缓存,parameterMap貌似没啥用了这个,resultMap重点,复用sql,执行sql

计算机生成了可选文字:context . getStr1ngAttr1bute( " Str1ng namespace bullderAssistant.setCurr 、 entNamespace namespace cacheRefE1ement(context . evalNode( " cache _ ref" ) ) ; cacheE1ement(context . evalNode( " cache " ) ) ; par 、 ameterMapE1ement (context . evalNodes ( " /mapper 、 /par 、 ameterMap" ) ) , , 、 esu1tMapE1ements (context . evalNodes ( " /mapper 、 /, 、 esu1tMap" ) ) , sq1E1ement(context . evalNodes ( " /mappep/sql " ) ) ; buildStatementFromContext(context . evalNodes ( " select 丨 Insert 丨 update 丨 delete " ) ) ,

命名空间就不说了

4.1缓存创建

缓存是根据命名空间来做的,每个命名空间new一个缓存

计算机生成了可选文字:if (context ! null) { context . getStr 、 IngAttr 、 Ibute ( "type ' " PERPETUAL " ) ; Str 、 Ing type typeA11asReg1st , 、 es01veA11as(type), Classe extends Cache) typeC1ass context . getStr1ngAttr1bute( " ev1ct10n " LRU" ) ; Str1ng ev1ct10n typeA11asReg1st , 、 es01veA11as(ev1ct10n) Classe extends Cache) ev1ct10nC1ass 、 ops ) ; context . getLongAttr1bute( "flushlntepval " ) ; Long flushlnterval context . getIntAttr1bute( " s 工 z e ' Integer 、 s 工 z e ! context . getB001eanAttr1bute( , false) , boolean readWr1te readOn1y context . getCh11drenAsPropert1es Propertles props bullderAss1stant.useNewCache(typeC1ass, ev1ct10nC1ass, flushlnter 、 Val, S 工 Z e readWr1te

cachemybatis也比较简单先用map实现一个PerpetualCache,然后用装饰器模式,弄一堆缓存,包括LRU,Fifo,Scheduled等带有附加功能的缓存,其实调用的还是PerpetualCache,默认的是LRU,说一下LRU实现及其简单,是用的LinkedHashMap访问排序功能,简易实现了,然后后面的sql就会调用了,这里显示下cacheKey的生成

计算机生成了可选文字:CacheKey cacheKey cacheKey cacheKey cacheKey cacheKey new CacheKey(), .update()s .getld()); . update(rowBounds . getOffset ( ) ) ; . update(r 、 owBounds . getL1m1t()) ; . update(boundSq1 . getSq1()) ; L1st(Par 、 ameterMapp1ng) par 、 ameterMapp1ngs boundSq1 . getPar 、 ameterMapp1ngs() , ( ) . getTypeHand1er 、 Reglstry() ; TypeHand1er 、 Reglstry typeHand1er 、 Reglstry ms . getConf1gur 、 atlon for (int 1 9 ; 工 < par 、 ameterMapp1ngs.S1ze i++) { / / mimic DefaultPapametepHand1ep logic par 、 ameterMapp1ngs . get(1) , ParameterMapP1ng parameterMapP1ng if (par 、 ameterMapp1ng. getMode ( ) ! par 、 ameterMode . OU 丆 ) { (b) ect value par 、 ameterMapp1ng . getProperty( ) , Str 、 Ing 、 opertyName if (boundSq1.hasAdd1t10na1Par 、 ameter 、 ()r 、 opertyName boundSq1 . getAdd1t10na1Par 、 ameter 、 ()r 、 opertyName } else if ( par 、 ameterObJ ect null) { null; } else if (typeHand1er 、 Reglstry hasTypeHand1er 、 (par 、 ameterObJect.getC1ass ( ) ) ) { par 、 ameterObJ ect ; } else { confIgu ratlon . newMetaObJ ect ( par 、 ameterObJ ect) , MetaObJ ect metaObJ ect metaObJ ect . getVa1ue ( 、 opertyName cacheKey update(value),

用了很多条件确保了key的唯一性

4.2resultMap

4.2.1解析一下简单参数

计算机生成了可选文字:resultMapNode . getStr1ngAttr1bute ( " Id " Str 、 Ing Id , 、 esu1tMapNode . getVa1ueBasedIdent1f1er( ) ) ; , 、 esu1tMapNode . getStr1ngAttr1bute ( "type ' Str 、 Ing type , 、 esu1tMapNode . getStr1ngAttr1bute ( " ofType , , 、 esu1tMapNode . getStr1ngAttr1bute ( " resultType ' , 、 esu1tMapNode . getStringAttr1bute( " ] avaType " ) ) ) ) ; , 、 esu1tMapNode . getStr 、 IngAttr 、 Ibute( " extends " ) ; Str 、 Ing extend resolveC1ass (type); Classe) typeC1ass

 

4.2.1ResultMapping 其实就是我们写的resultjava对象

计算机生成了可选文字:public class esu1tMapp1n { private private private private private private private private private private private Conflgur 、 atlon conflgupatlon. Str 、 Ing prope Pty . Str 、 Ing column. Class ] avaType ; DdbcType ] dbcType ; TypeHand1er 、 typeHand1ep. Str 、 Ing nestedResu1tMapId; Str 、 Ing nestedQuepyId; Set(Strlng) notNu11C01umns; LIst(Resu1tF1ag) flags; LIst(Resu1tMapP1ng) composltes .

然后解析xml把值配置到对象中

计算机生成了可选文字:private ResultMapP1ng buildResu1tMapp1ngFromContext(XNode context, context . getStr1ngAttr1bute( " prope Pty ' ) , Str 、 Ing 、 operty context . getStr1ngAttr1bute ( " column Str 、 Ing column context . getStr1ngAttr1bute( " ] avaType " ) , Str1ng JavaType context . getStr1ngAttr1bute( " j dbcType " ) ; Str1ng JdbcType context . getStr1ngAttr1bute( " select " ) ; Str 、 Ing nestedSe1ect context . getStr1ngAttr1bute( " Str 、 Ing nestedResu1tMap , 、 esu1tMap Classo) , 、 esu1tType, A,当 、 ayL1st(Resu1tF1ag) flags) throws Exceptlon nestedResu1tMap, pr 、 ocessNestedResu1tMapp1ngs(context, Collect10ns.EMPTY 廴 了 ST ) ) ; context . getStr1ngAttr1bute( " Str 、 Ing notNu11C01umn notNu11C01umn context . getStr1ngAttr1bute( "typeHand1ep ' Str 、 Ing typeHand1er 、 , 、 es01veC1ass(JavaType); Classo) JavaTypeC1ass (Classe extends TypeHand1er 、 >) , 、 es01veC1ass(typeHand1er 、 ), Classe extends TypeHand1er 、 > typeHand1erC1ass resolveJdbcType(JdbcType); DdbcType JdbcTypeEnum return builderAss1stant.bui1dResu1tMapP1ng(r 、 esu1tType, 、 operty, column , ] avaTypeC1ass , JdbcTypeEnum, nestedSe1ect,

4.2.4这些参数以及这个list组合成为一个resultMap

计算机生成了可选文字:public ResultMap addResu1tMap( Str 、 Ing 工 d , Classo) type , Str 、 Ing extend, LIst(Resu1tMapP1ng) , 、 esu1tMapp1ngs) { applyCurrentNamespace (Id) ; applyCurr 、 entNamespace (extend) , extend new ResultMap.Bu11der 、 (conflgur 、 atlon, 工 d , type , , 、 esu1tMapp1ngs), ResultMap.Bu11der 、 , 、 esu1tMapBu11der 、 if (extend ! null) { if (!conflgur 、 atlon.hasResu1tMap(extend)) { throw new IncompleteResu1tMapExcept10n("Cou1d not find a pa pent resultmap w1th id confIgu ratlon . getResu1tMap(extend) , ResultMap resultMap + + new A,当 、 ayL1st(Resu1tMapp1ng)(r 、 esu1tMap.getResu1tMaPP1ngs()), LIst(Resu1tMapP1ng) extendedResu1tMapP1ngs extendedResu1tMapP1ngs . removeA110 、 esu1tMapp1ngs) , , 、 esu1tMapp1ngs . addA11 (extendedResu1tMapP1ngs) , , 、 esu1tMapBu11der 、 . d 工 sc , 、 工 m 工 nato , 、 ( d 工 sc , 、 工 m 工 nato , 、 ) , resultMapBu11der . bulld() ; ResultMap resultMap conflgur 、 atlon . addReku1tMap(r 、 esu1tMap) ; return , 、 esu1tMap;

4.3重复的sql

这个简单直接put

4.4执行sql

首先是设置一堆属性

计算机生成了可选文字:context . getStr1ngAttr1bute( " Id " ) , Str 、 Ing Id context . getIntAttr1bute( "fetchS1ze , null); Integer 、 fetchS1ze context . getIntAttr1bute ( "tlmeout " null); Integer 、 tlmeout context . getStr1ngAttr1bute( " par 、 ameterMap" ) , Str 、 Ing par 、 ameterMap context . getStr1ngAttr1bute( " pa ramete pType " ) , Str 、 Ing par 、 ameter 、 Type resolveC1ass (parameterType) , Classo) par 、 ameter 、 TypeC1ass context . getStr1ngAttr1bute( " , 、 esu1tMap" ) ; Str 、 Ing , 、 esu1tMap context . getStr 、 IngAttr 、 Ibute( " resultType " ) , Str 、 Ing , 、 esu1tType resolveC1ass 、 esu1tType) , Classo) , 、 esu1tTypeC1ass context . getStr1ngAttr1bute( " resultSetType " ) , Str1ng resultSetType

通过一系列的hanlder把动态xml解析

计算机生成了可选文字:new IncludeNoEeHand1er 、 ()); put ( " Include" put( " new Tr 、 1mHand1er 、 ()); put( " new Wher 、 eHand1er 、 ()); put( " new SetHand1er 、 ()); set " put(' new For 、 EachHand1er 、 ()), 'foreach put(' 'if", new IfHandler()); put( " new ChooseHand1er 、 ()); Choose put( " n ew IfHandler 、 ()); put( " new Otherw1seHand1er 、 ()); put( " new SelectKeyHand1er 、 ()); selectKey

然后拼装成为

计算机生成了可选文字:public MappedStatement addr'!appedStatement Str1ng 工 d , Sq1Sour 、 ce sq1Sour 、 ce StatementType statementType , Sq1CommandType sq1CommandType, Integer 、 fetchS1ze Integer 、 tlmeout, Str 、 Ing par 、 ameterMap, Classo) par 、 ameter 、 Type , Str 、 Ing , 、 esu1tMap, Classo) , 、 esu1tType, ResultSetType , 、 esu1tSetType, boolean flushCache boolean useCache KeyGenerator keyGener 、 ator 、 Str 、 Ing keypr 、 operty) { applyCurr 、 entNamespace (Id) , boolean 1sSe1ect sq1CommandType Sq1CommandType . SE ECT; new MappedStatement.Bu11der 、 (conflgur 、 at10 MappedStatement.Bu11der 、 statementBu11der e S Ou C e S Ou PC e statementBu11der . fetchS1ze(fetchS1ze statementBu11der . statementType ( statementType ) , statementBu11der . keyGener 、 ator 、 (keyGener 、 ator 、 ) , statementBu11der . keyProperty(keyProperty) ; setStatementT1meout(t1meout, statementBu11der 、 ), setStatementPar 、 ameterMap(par 、 ameterMap, par 、 ameter 、 Type , statementBu11der 、 ), setStatementResu1tMap(r 、 esu1tMap, resultType, resultSetType, statementBu11der 、 ), setStatementCache(1sSe1ect, flushCache, useCache, currentCache, statementBu11der 、 ),

这个对象是及其重要的,基本上包含了一个sql的所有信息,之后查询的时候就可以根据这个信息来进行反射set对象了

 

到这里mybatis也基本上初始化完成了

0 0