先写个小demo,如下。相关配置文件就不贴出来了。官网上直接可以复制
public static void main(String[] args) throws IOException {
Reader reader = Resources.getResourceAsReader("com/forcht/testMybatis/mybatis-config.xml");
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
PaperMapper mapper = session.getMapper(PaperMapper.class);
System.out.println(mapper.selectPaper(1));
}
1、如何加载配置文件
使用Resources类将配置文件加载为Reader。
第一步
//调用getResourceAsReader。
Reader reader = Resources.getResourceAsReader("com/forcht/testMybatis/mybatis-config.xml");
第二步
//进入getResourceAsReader方法。使用InputStreamReader将InputStream包装成Reader
public static Reader getResourceAsReader(String resource) throws IOException {
Reader reader;
if (charset == null) {
reader = new InputStreamReader(getResourceAsStream(resource));
} else {
reader = new InputStreamReader(getResourceAsStream(resource), charset);
}
return reader;
}
第三步
//进入getResourceAsStream加载InputStream
public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
//classLoaderWrapper包装了几种类加载器。
//每次回按顺序选择第一个可用的加载器
InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
if (in == null) {
throw new IOException("Could not find resource " + resource);
}
return in;
}
第四步
//选择一个类加载器来加载文件,包装成InputStream
//选择第一个可以用的加载器,这里不明白为什么要这么做
//(直接都指定为其中一个不就好了?有大佬看到可以解答下)
InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
for (ClassLoader cl : classLoader) {
if (null != cl) {
// try to find the resource as passed
InputStream returnValue = cl.getResourceAsStream(resource);
// now, some class loaders want this leading "/", so we'll add it and try again if we didn't find the resource
if (null == returnValue) {
returnValue = cl.getResourceAsStream("/" + resource);
}
if (null != returnValue) {
return returnValue;
}
}
}
return null;
}
2、创建SqlSessionFactory
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);
第一步
//创建一个XMLConfigBuilder,再调用XMLConfigBuilder的parse()方法获取一个Configuration对象
//并使用该对象去build一个SqlSessionFactory
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
第二步
//创建XMLConfigBuilder时,会先创建一个XPathParser和XMLMapperEntityResolver
public XMLConfigBuilder(Reader reader, String environment, Properties props) {
this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
}
第三步
//进入XMLConfigBuilder的parse()方法
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
//获取<configuration>根节点,进行解析
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
第四步
//这里就是解析所有的子节点的过程
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);
}
}