1.使用步骤
//加载核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//解析配置文件得到SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//得到sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取Mapper接口对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//测试
int res = mapper.insertUser();
System.out.println(res);
2.加载核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
Resources类提供了多种获取资源文件的方法:
我们选择了其中一种方法: getResourceAsStream(String resource)
跟踪该方法发现其间接调用了以下方法:
//Resources类中的方法
public static InputStream getResourceAsStream(String resource) throws IOException {
//直接调用重载方法
return getResourceAsStream(null, resource);
}
public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
//classLoaderWrapper是Resources类的一个成员属性
InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
if (in == null) {
throw new IOException("Could not find resource " + resource);
}
return in;
}
//classLoaderWrapper类中的方法
public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
//直接调用重载方法
return getResourceAsStream(resource, getClassLoaders(classLoader));
}
//返回一个类加载器数组
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
return new ClassLoader[]{
classLoader,//参数传入的加载器
defaultClassLoader,//当前类的成员属性加载器
Thread.currentThread().getContextClassLoader(),
getClass().getClassLoader(),//加载当前类的类加载器
systemClassLoader};//当前类的成员属性加载器,构造方法时初始化为systemClassLoader
}
//遍历该加载器数组,通过类加载器的getResourceAsStream方法得到InputStream对象
InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
for (ClassLoader cl : classLoader) {
if (null != cl) { //遍历该 加载器类数组,找到第一个不为空的加载器对象,调用它的getResourceAsStream方法得到InputStream对象
// 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;
}
总结 : InputStream is = Resources.getResourceAsStream(“mybatis-config.xml”);该代码底层通过调用类加载器的getResourceAsStream方法获取到InputStream对象并返回。
2. 解析配置文件得到SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
类SqlSessionFactoryBuilder:
该类中的所有方法都是build方法的重载,主要对字符流,字节流,Configuration进行处理。
跟进我们使用的这个方法:
public SqlSessionFactory build(InputStream inputStream)
间接调用了如下方法 :
SqlSessionFactoryBuilder 的部分源码
public SqlSessionFactory build(InputStream inputStream) {
//直接调用重载方法
return build(inputStream, null, null);
}
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
//创建一个XMLConfigBuilder对象
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//调用处理Configuration的build方法,parser.parse()方法返回一个Configuration对象
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
XMLConfigBuilder的部分源码
XMLConfigBuilder继承自BaseBuilder,BaseBuilder类有许多以Builder结尾的子类,这里使用了建造者模式。
public class XMLConfigBuilder extends BaseBuilder
XMLConfigBuilder部分源码:
private boolean parsed;
private final XPathParser parser;
private String environment;
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
//调用下面的重载构造方法
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration()); //初始化父类
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
//初始化当前类的三个属性
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
//该方法为Configuration设置属性值,通过调用不同的方法读取xml配置来设置对应的属性
//Configuration存放着Mybatis的所有配置信息
private void parseConfiguration(XNode root) {
try {
// issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
loadCustomLogImpl(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);
}
}
XPathParser 类的部分源码:
private final Document document;
private boolean validation;
private EntityResolver entityResolver;
private Properties variables;
private XPath xpath;
public XNode evalNode(String expression) {
return evalNode(document, expression);
}
public XNode evalNode(Object root, String expression) {
Node node = (Node) evaluate(expression, root, XPathConstants.NODE);
if (node == null) {
return null;
}
return new XNode(this, node, variables);
}
版权声明:本文为weixin_52907605原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。