源码流程图
源码
加载xml资源代码
private void loadXmlResource ( ) {
if ( ! configuration. isResourceLoaded ( "namespace:" + type. getName ( ) ) ) {
String xmlResource = type. getName ( ) . replace ( '.' , '/' ) + ".xml" ;
InputStream inputStream = type. getResourceAsStream ( "/" + xmlResource) ;
if ( inputStream == null) {
try {
inputStream = Resources. getResourceAsStream ( type. getClassLoader ( ) , xmlResource) ;
} catch ( IOException e2) {
}
}
if ( inputStream != null) {
XMLMapperBuilder xmlParser = new XMLMapperBuilder ( inputStream, assistant. getConfiguration ( ) , xmlResource, configuration. getSqlFragments ( ) , type. getName ( ) ) ;
xmlParser. parse ( ) ;
}
}
}
解析xml xmlParser.parse()
public void parse ( ) {
if ( ! configuration. isResourceLoaded ( resource) ) {
configurationElement ( parser. evalNode ( "/mapper" ) ) ;
configuration. addLoadedResource ( resource) ;
bindMapperForNamespace ( ) ;
}
parsePendingResultMaps ( ) ;
parsePendingCacheRefs ( ) ;
parsePendingStatements ( ) ;
}
解析mapper节点 configurationElement
private void configurationElement ( XNode context) {
try {
String namespace = context. getStringAttribute ( "namespace" ) ;
if ( namespace == null || namespace. equals ( "" ) ) {
throw new BuilderException ( "Mapper's namespace cannot be empty" ) ;
}
builderAssistant. setCurrentNamespace ( namespace) ;
cacheRefElement ( context. evalNode ( "cache-ref" ) ) ;
cacheElement ( context. evalNode ( "cache" ) ) ;
parameterMapElement ( context. evalNodes ( "/mapper/parameterMap" ) ) ;
resultMapElements ( context. evalNodes ( "/mapper/resultMap" ) ) ;
sqlElement ( context. evalNodes ( "/mapper/sql" ) ) ;
buildStatementFromContext ( context. evalNodes ( "select|insert|update|delete" ) ) ;
} catch ( Exception e) {
throw new BuilderException ( "Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e) ;
}
}
二级缓存
cacheElement 解析二级缓存
private void cacheElement ( XNode context) {
if ( context != null) {
String type = context. getStringAttribute ( "type" , "PERPETUAL" ) ;
Class< ? extends Cache > typeClass = typeAliasRegistry. resolveAlias ( type) ;
String eviction = context. getStringAttribute ( "eviction" , "LRU" ) ;
Class< ? extends Cache > evictionClass = typeAliasRegistry. resolveAlias ( eviction) ;
Long flushInterval = context. getLongAttribute ( "flushInterval" ) ;
Integer size = context. getIntAttribute ( "size" ) ;
boolean readWrite = ! context. getBooleanAttribute ( "readOnly" , false ) ;
boolean blocking = context. getBooleanAttribute ( "blocking" , false ) ;
Properties props = context. getChildrenAsProperties ( ) ;
builderAssistant. useNewCache ( typeClass, evictionClass, flushInterval, size, readWrite, blocking, props) ;
}
}
useNewCache 构造二级缓存
public Cache useNewCache ( Class< ? extends Cache > typeClass,
Class< ? extends Cache > evictionClass,
Long flushInterval,
Integer size,
boolean readWrite,
boolean blocking,
Properties props) {
Cache cache = new CacheBuilder ( currentNamespace)
. implementation ( valueOrDefault ( typeClass, PerpetualCache. class ) )
. addDecorator ( valueOrDefault ( evictionClass, LruCache. class ) )
. clearInterval ( flushInterval)
. size ( size)
. readWrite ( readWrite)
. blocking ( blocking)
. properties ( props)
. build ( ) ;
configuration. addCache ( cache) ;
currentCache = cache;
return cache;
}
解析resultMap
private void resultMapElements ( List< XNode> list) throws Exception {
for ( XNode resultMapNode : list) {
try {
resultMapElement ( resultMapNode) ;
} catch ( IncompleteElementException e) {
}
}
}
private ResultMap resultMapElement ( XNode resultMapNode, List< ResultMapping> additionalResultMappings, Class< ? > enclosingType) throws Exception {
ErrorContext. instance ( ) . activity ( "processing " + resultMapNode. getValueBasedIdentifier ( ) ) ;
String type = resultMapNode. getStringAttribute ( "type" ,
resultMapNode. getStringAttribute ( "ofType" ,
resultMapNode. getStringAttribute ( "resultType" ,
resultMapNode. getStringAttribute ( "javaType" ) ) ) ) ;
Class< ? > typeClass = resolveClass ( type) ;
if ( typeClass == null) {
typeClass = inheritEnclosingType ( resultMapNode, enclosingType) ;
}
Discriminator discriminator = null;
List< ResultMapping> resultMappings = new ArrayList < > ( ) ;
resultMappings. addAll ( additionalResultMappings) ;
List< XNode> resultChildren = resultMapNode. getChildren ( ) ;
for ( XNode resultChild : resultChildren) {
if ( "constructor" . equals ( resultChild. getName ( ) ) ) {
processConstructorElement ( resultChild, typeClass, resultMappings) ;
} else if ( "discriminator" . equals ( resultChild. getName ( ) ) ) {
discriminator = processDiscriminatorElement ( resultChild, typeClass, resultMappings) ;
} else {
List< ResultFlag> flags = new ArrayList < > ( ) ;
if ( "id" . equals ( resultChild. getName ( ) ) ) {
flags. add ( ResultFlag. ID) ;
}
resultMappings. add ( buildResultMappingFromContext ( resultChild, typeClass, flags) ) ;
}
}
String id = resultMapNode. getStringAttribute ( "id" ,
resultMapNode. getValueBasedIdentifier ( ) ) ;
String extend = resultMapNode. getStringAttribute ( "extends" ) ;
Boolean autoMapping = resultMapNode. getBooleanAttribute ( "autoMapping" ) ;
ResultMapResolver resultMapResolver = new ResultMapResolver ( builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping) ;
try {
return resultMapResolver. resolve ( ) ;
} catch ( IncompleteElementException e) {
configuration. addIncompleteResultMap ( resultMapResolver) ;
throw e;
}
}
解析sql节点
private void sqlElement ( List< XNode> list, String requiredDatabaseId) {
for ( XNode context : list) {
String databaseId = context. getStringAttribute ( "databaseId" ) ;
String id = context. getStringAttribute ( "id" ) ;
id = builderAssistant. applyCurrentNamespace ( id, false ) ;
if ( databaseIdMatchesCurrent ( id, databaseId, requiredDatabaseId) ) {
sqlFragments. put ( id, context) ;
}
}
}
解析select|insert|update|delete
构造Statement
private void buildStatementFromContext ( List< XNode> list, String requiredDatabaseId) {
for ( XNode context : list) {
final XMLStatementBuilder statementParser = new XMLStatementBuilder ( configuration, builderAssistant, context, requiredDatabaseId) ;
try {
statementParser. parseStatementNode ( ) ;
} catch ( IncompleteElementException e) {
configuration. addIncompleteStatement ( statementParser) ;
}
}
}
将节点解析成Statement
public void parseStatementNode ( ) {
String id = context. getStringAttribute ( "id" ) ;
String databaseId = context. getStringAttribute ( "databaseId" ) ;
if ( ! databaseIdMatchesCurrent ( id, databaseId, this . requiredDatabaseId) ) {
return ;
}
String nodeName = context. getNode ( ) . getNodeName ( ) ;
SqlCommandType sqlCommandType = SqlCommandType. valueOf ( nodeName. toUpperCase ( Locale. ENGLISH) ) ;
boolean isSelect = sqlCommandType == SqlCommandType. SELECT;
boolean flushCache = context. getBooleanAttribute ( "flushCache" , ! isSelect) ;
boolean useCache = context. getBooleanAttribute ( "useCache" , isSelect) ;
boolean resultOrdered = context. getBooleanAttribute ( "resultOrdered" , false ) ;
XMLIncludeTransformer includeParser = new XMLIncludeTransformer ( configuration, builderAssistant) ;
includeParser. applyIncludes ( context. getNode ( ) ) ;
String parameterType = context. getStringAttribute ( "parameterType" ) ;
Class< ? > parameterTypeClass = resolveClass ( parameterType) ;
String lang = context. getStringAttribute ( "lang" ) ;
LanguageDriver langDriver = getLanguageDriver ( lang) ;
processSelectKeyNodes ( id, parameterTypeClass, langDriver) ;
KeyGenerator keyGenerator;
String keyStatementId = id + SelectKeyGenerator. SELECT_KEY_SUFFIX;
keyStatementId = builderAssistant. applyCurrentNamespace ( keyStatementId, true ) ;
if ( configuration. hasKeyGenerator ( keyStatementId) ) {
keyGenerator = configuration. getKeyGenerator ( keyStatementId) ;
} else {
keyGenerator = context. getBooleanAttribute ( "useGeneratedKeys" ,
configuration. isUseGeneratedKeys ( ) && SqlCommandType. INSERT. equals ( sqlCommandType) )
? Jdbc3KeyGenerator. INSTANCE : NoKeyGenerator. INSTANCE;
}
SqlSource sqlSource = langDriver. createSqlSource ( configuration, context, parameterTypeClass) ;
StatementType statementType = StatementType. valueOf ( context. getStringAttribute ( "statementType" , StatementType. PREPARED. toString ( ) ) ) ;
Integer fetchSize = context. getIntAttribute ( "fetchSize" ) ;
Integer timeout = context. getIntAttribute ( "timeout" ) ;
String parameterMap = context. getStringAttribute ( "parameterMap" ) ;
String resultType = context. getStringAttribute ( "resultType" ) ;
Class< ? > resultTypeClass = resolveClass ( resultType) ;
String resultMap = context. getStringAttribute ( "resultMap" ) ;
String resultSetType = context. getStringAttribute ( "resultSetType" ) ;
ResultSetType resultSetTypeEnum = resolveResultSetType ( resultSetType) ;
if ( resultSetTypeEnum == null) {
resultSetTypeEnum = configuration. getDefaultResultSetType ( ) ;
}
String keyProperty = context. getStringAttribute ( "keyProperty" ) ;
String keyColumn = context. getStringAttribute ( "keyColumn" ) ;
String resultSets = context. getStringAttribute ( "resultSets" ) ;
builderAssistant. addMappedStatement ( id, sqlSource, statementType, sqlCommandType,
fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
resultSetTypeEnum, flushCache, useCache, resultOrdered,
keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets) ;
}
创建createSqlSource
public SqlSource createSqlSource ( Configuration configuration, XNode script, Class< ? > parameterType) {
XMLScriptBuilder builder = new XMLScriptBuilder ( configuration, script, parameterType) ;
return builder. parseScriptNode ( ) ;
}
解析脚本
public SqlSource parseScriptNode ( ) {
MixedSqlNode rootSqlNode = parseDynamicTags ( context) ;
SqlSource sqlSource;
if ( isDynamic) {
sqlSource = new DynamicSqlSource ( configuration, rootSqlNode) ;
} else {
sqlSource = new RawSqlSource ( configuration, rootSqlNode, parameterType) ;
}
return sqlSource;
}
真正开始解析
protected MixedSqlNode parseDynamicTags ( XNode node) {
List< SqlNode> contents = new ArrayList < > ( ) ;
NodeList children = node. getNode ( ) . getChildNodes ( ) ;
for ( int i = 0 ; i < children. getLength ( ) ; i++ ) {
XNode child = node. newXNode ( children. item ( i) ) ;
if ( child. getNode ( ) . getNodeType ( ) == Node. CDATA_SECTION_NODE || child. getNode ( ) . getNodeType ( ) == Node. TEXT_NODE) {
String data = child. getStringBody ( "" ) ;
TextSqlNode textSqlNode = new TextSqlNode ( data) ;
if ( textSqlNode. isDynamic ( ) ) {
contents. add ( textSqlNode) ;
isDynamic = true ;
} else {
contents. add ( new StaticTextSqlNode ( data) ) ;
}
} else if ( child. getNode ( ) . getNodeType ( ) == Node. ELEMENT_NODE) {
String nodeName = child. getNode ( ) . getNodeName ( ) ;
NodeHandler handler = nodeHandlerMap. get ( nodeName) ;
if ( handler == null) {
throw new BuilderException ( "Unknown element <" + nodeName + "> in SQL statement." ) ;
}
handler. handleNode ( child, contents) ;
isDynamic = true ;
}
}
return new MixedSqlNode ( contents) ;
}