Mybatis官方文档
https://mybatis.org/mybatis-3/zh/logging.html
mybatis源码分析如何获取数据源和SQL语句
Mybatis源码分析
一、mybatis如何获取数据源
org.apache.ibatis.session.SqlSessionFactoryBuilder.build(java.io.InputStream)
》org.apache.ibatis.builder.xml.XMLConfigBuilder.parse
》org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration
》org.apache.ibatis.builder.xml.XMLConfigBuilder.environmentsElement
》org.apache.ibatis.builder.xml.XMLConfigBuilder.dataSourceElement
》org.apache.ibatis.session.Configuration.setEnvironment#######
123456
1、org.apache.ibatis.session.SqlSessionFactoryBuilder.build(java.io.InputStream)
获取mybatis-config.xml文件
2、org.apache.ibatis.builder.xml.XMLConfigBuilder.parse
加载mybatis-config.xml配置文件
3、org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration
对mybatis-config.xml文件进行解析
private void parseConfiguration(XNode root) {
try {
//获取Properties标签中的内容
this.propertiesElement(root.evalNode("properties"));
//获取缓存
Properties settings = this.settingsAsProperties(root.evalNode("settings"));
this.loadCustomVfs(settings);
//加载别名
this.typeAliasesElement(root.evalNode("typeAliases"));
//加载拦截器
this.pluginElement(root.evalNode("plugins"));
//用于加载对象工厂(用于创建对象的实例)
this.objectFactoryElement(root.evalNode("objectFactory"));
//用于加载对象包装工程
this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
//用于反射实体类中的属性字段
this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
this.settingsElement(settings);
//加载数据源
this.environmentsElement(root.evalNode("environments"));
this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
//用于实现JDBC和JAVA类型之间的转换
this.typeHandlerElement(root.evalNode("typeHandlers"));
//加载Mappers标签中的内容,也就是写SQL语句的位置
this.mapperElement(root.evalNode("mappers"));
} catch (Exception var3) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
}
}
1234567891011121314151617181920212223242526272829
4、org.apache.ibatis.builder.xml.XMLConfigBuilder.environmentsElement
加载数据源
private void environmentsElement(XNode context) throws Exception {
if (context != null) {
if (this.environment == null) {
this.environment = context.getStringAttribute("default");
}
Iterator var2 = context.getChildren().iterator();
while(var2.hasNext()) {
XNode child = (XNode)var2.next();
String id = child.getStringAttribute("id");
if (this.isSpecifiedEnvironment(id)) {
TransactionFactory txFactory = this.transactionManagerElement(child.evalNode("transactionManager"));
//下面这个方法会对数据源进行解析
DataSourceFactory dsFactory = this.dataSourceElement(child.evalNode("dataSource"));
//获取到数据源
DataSource dataSource = dsFactory.getDataSource();
Builder environmentBuilder = (new Builder(id)).transactionFactory(txFactory).dataSource(dataSource);
this.configuration.setEnvironment(environmentBuilder.build());
}
}
}
}
1234567891011121314151617181920212223
5、org.apache.ibatis.builder.xml.XMLConfigBuilder.dataSourceElement
解析数据源
private DataSourceFactory dataSourceElement(XNode context) throws Exception {
if (context != null) {
//获取dataSource标签的一个类型
String type = context.getStringAttribute("type");
//取出数据源,Driver、URL、Username、Password
Properties props = context.getChildrenAsProperties();
//通过反射的形式来获取对应的工厂实例
DataSourceFactory factory = (DataSourceFactory)this.resolveClass(type).newInstance();
factory.setProperties(props);
return factory;
} else {
throw new BuilderException("Environment declaration requires a DataSourceFactory.");
}
}
1234567891011121314
6、org.apache.ibatis.session.Configuration.setEnvironment
加载数据源会放在这个类中,包括了连接的最大数量、最小数量、过期时间等
二、mybatis是如何获取SQL语句的
org.apache.ibatis.session.SqlSessionFactoryBuilder.build(java.io.InputStream)
》org.apache.ibatis.builder.xml.XMLConfigBuilder.parse
》org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration
》org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement
》org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement
》org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode
>org.apache.ibatis.session.Configuration.addMappedStatement######
1234567
1、org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement
解析Mapper的加载方式
private void mapperElement(XNode parent) throws Exception {
/**
* parent的内容是Mappers标签中的内容(包括了Mappers标签)
* <mappers>
* <mapper resource="mapper/ExJobMapper.xml"/>
* </mappers>
*/
if (parent != null) {
Iterator var2 = parent.getChildren().iterator();
while(true) {
while(var2.hasNext()) {
XNode child = (XNode)var2.next();
String resource;
//判断Mappers的加载方式是否为Package,优先判断
if ("package".equals(child.getName())) {
resource = child.getStringAttribute("name");
this.configuration.addMappers(resource);
} else {
resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
XMLMapperBuilder mapperParser;
InputStream inputStream;
//判断加载方式是否为Resource
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
inputStream = Resources.getResourceAsStream(resource);
mapperParser = new XMLMapperBuilder(inputStream, this.configuration, resource, this.configuration.getSqlFragments());
mapperParser.parse();
//判断加载方式是否为URL
} else if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
inputStream = Resources.getUrlAsStream(url);
mapperParser = new XMLMapperBuilder(inputStream, this.configuration, url, this.configuration.getSqlFragments());
mapperParser.parse();
} else {
//判断加载方式是否为Class加载
if (resource != null || url != null || mapperClass == null) {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
Class<?> mapperInterface = Resources.classForName(mapperClass);
this.configuration.addMapper(mapperInterface);
}
}
}
return;
}
}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
2、org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement
解析Mappers中的各种相关配置
private void configurationElement(XNode context) {
try {
//获取命名空间
String namespace = context.getStringAttribute("namespace");
if (namespace != null && !namespace.equals("")) {
//设置命名空间
this.builderAssistant.setCurrentNamespace(namespace);
//用于引用另一个缓存
this.cacheRefElement(context.evalNode("cache-ref"));
//设置缓存(默认为一级缓存)
this.cacheElement(context.evalNode("cache"));
//关系映射,数据一一映射到实体类属性当中
this.parameterMapElement(context.evalNodes("/mapper/parameterMap"));
this.resultMapElements(context.evalNodes("/mapper/resultMap"));
//解析SQL语句
this.sqlElement(context.evalNodes("/mapper/sql"));
//判断SQL语句是DQL还是DML
this.buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
} else {
throw new BuilderException("Mapper's namespace cannot be empty");
}
} catch (Exception var3) {
throw new BuilderException("Error parsing Mapper XML. The XML location is '" + this.resource + "'. Cause: " + var3, var3);
}
}
12345678910111213141516171819202122232425
3、org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode
解析Mappers中SQL标签的各种配置
public void parseStatementNode() {
//获取SQL标签中的Id
String id = this.context.getStringAttribute("id");
//数据库的ID
String databaseId = this.context.getStringAttribute("databaseId");
if (this.databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
Integer fetchSize = this.context.getIntAttribute("fetchSize");
Integer timeout = this.context.getIntAttribute("timeout");
String parameterMap = this.context.getStringAttribute("parameterMap");
String parameterType = this.context.getStringAttribute("parameterType");
Class<?> parameterTypeClass = this.resolveClass(parameterType);
String resultMap = this.context.getStringAttribute("resultMap");
String resultType = this.context.getStringAttribute("resultType");
String lang = this.context.getStringAttribute("lang");
LanguageDriver langDriver = this.getLanguageDriver(lang);
Class<?> resultTypeClass = this.resolveClass(resultType);
String resultSetType = this.context.getStringAttribute("resultSetType");
StatementType statementType = StatementType.valueOf(this.context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
ResultSetType resultSetTypeEnum = this.resolveResultSetType(resultSetType);
//获取标签头(例如SELECT、DELETE、UPDATE、INSERT)
String nodeName = this.context.getNode().getNodeName();
SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
boolean flushCache = this.context.getBooleanAttribute("flushCache", !isSelect);
boolean useCache = this.context.getBooleanAttribute("useCache", isSelect);
boolean resultOrdered = this.context.getBooleanAttribute("resultOrdered", false);
XMLIncludeTransformer includeParser = new XMLIncludeTransformer(this.configuration, this.builderAssistant);
includeParser.applyIncludes(this.context.getNode());
this.processSelectKeyNodes(id, parameterTypeClass, langDriver);
//获取到完整的一条SQL语句
SqlSource sqlSource = langDriver.createSqlSource(this.configuration, this.context, parameterTypeClass);
String resultSets = this.context.getStringAttribute("resultSets");
String keyProperty = this.context.getStringAttribute("keyProperty");
String keyColumn = this.context.getStringAttribute("keyColumn");
String keyStatementId = id + "!selectKey";
keyStatementId = this.builderAssistant.applyCurrentNamespace(keyStatementId, true);
Object keyGenerator;
if (this.configuration.hasKeyGenerator(keyStatementId)) {
keyGenerator = this.configuration.getKeyGenerator(keyStatementId);
} else {
keyGenerator = this.context.getBooleanAttribute("useGeneratedKeys", this.configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType)) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
}
this.builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, (KeyGenerator)keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
4、org.apache.ibatis.session.Configuration.setEnvironment
将加载好的结果存放在该类中并且返回