Mybatis源码浅读一
String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); /** * 创建SqlSessionFactory工厂 */ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); // Listlist = session.selectList("org.apache.ibatis.test.pojo.UserDao.findAll"); UserDao mapper = session.getMapper(UserDao.class);
List list = mapper.findAll();
1.我们先看着几行的代码(单独mybatis 运行,没有与spring整合)
具体的流程是 :
a.先创建sqlSession 的工厂
b.通过sqlSession工厂得到SqlSession
c.SqlSession通过代理的方式得到mapper接口的代理对象
d.最后执行sql并得到结果集
2.我们关注流程的入口
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
从这个的表面上看 我们只是创建了SqlSessionFactory ,我们跟进源码看看
public SqlSessionFactory build(InputStream inputStream) { return build(inputStream, null, null); }
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { /** * 通过构造器得到XMLConfigBuilder 对象 * environment null * properties null * inputStream */ XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); 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. } } }
public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
看了这几部分的代码实质就是new DefaultSqlSessionFactory()对象,并返回。
我们虽然知道了SqlSessionFactory 的对象创建,但是我们更应该了解里面的构建过程
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { /** * 通过构造器得到XMLConfigBuilder 对象 * environment null * properties null * inputStream */ XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//重点分析 return build(parser.parse());
public class XMLConfigBuilder extends BaseBuilder { private boolean parsed; /** * xml 解析器 * * private final Document document; 表示整个 HTML或XML文档 * private boolean validation; * private EntityResolver entityResolver; 作用该xml文档上的声明,根据声明去寻找相应的dtd定义,以便对文档的进行验证, * private Properties variables; 该类主要用于读取Java的配置文件 * private XPath xpath; 用于解析XML的工具类对象 */ private final XPathParser parser; private String environment; private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory();
public class XPathParser { private final Document document; private boolean validation; private EntityResolver entityResolver; private Properties variables; private XPath xpath;
mybatis将配置文件的数据解析封装到了Document(XMLConfigBuilder------>XPathParser------->Document)中
我们跟进下return build(parser.parse());
public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; }
/** * 这个方法规定了对文档解析的流程 * @param root */ 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); } }
从这边我们可以知道这个方法对配置文件的每个属性节点的数据处理
初始化Mybatis的过程其实就是构建 Configuration 这个对象,Configuration对象包含了Mybatis运行所需要的所有配置项