MyBatis 源码分析——配置信息

MyBatis框架的启动前期需要加载相关的XML配置信息。从官网上我们得以精晓到她有着十多少个节点。其中笔者觉得相比首要的节点是settings节点、properties节点、environments节点、 transactionManager节点。至于有关的功效到官网看过一篇都会领会。

MyBatis框架的XML配置到底有多少个节点,这一个必须去查看一下相关的DTD文件才行。DTA文件就在包名为org.apache.ibatis.builder.xml的上面。由于显得的问题笔者只复制出部分来。

<?xml version="1.0" encoding="UTF-8" ?>

<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>

<!ELEMENT databaseIdProvider (property*)>
<!ATTLIST databaseIdProvider
type CDATA #REQUIRED
>

从地点大家就足以看看根节点就是configuration。同时我们也能找到地点笔者提到的可比关键的多少个节点。

1.properties 节点:可以把它理解为变量吧。事实上他可以是一个properties文件。
2.settings 节点:MyBatis框架有一些内部需要设置的配置信息。请查看官网对于settings的介绍。
3.typeAliases 节点:设置相应的别名。这样子可以简少重复的编写。
4.typeHandlers 节点:官网叫为类型处理器,大部用于结果集应射到对象的时候需要。
5.environments 节点:这个节点按道理来讲是大家最清楚的。因为设置数据连接的信息就在这里。
6.mappers 节点:对象模型与数据表映射的信息。
注意:笔者这里只是写出可能常用的。

略知一二了地点的信息之后,在去看对应的源码你就会发现很简短——大部分都是各类对应的。
来,让大家从上一章中讲到的切入口类(SqlSessionFactoryBuilder)的build方法查看进去。SqlSessionFactoryBuilder类里面重载了众多build的法子。可是富有的办法最终都会注入下边的点子中去。

 1 public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
 2     try {
 3       XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
 4       return build(parser.parse());
 5     } catch (Exception e) {
 6       throw ExceptionFactory.wrapException("Error building SqlSession.", e);
 7     } finally {
 8       ErrorContext.instance().reset();
 9       try {
10         reader.close();
11       } catch (IOException e) {
12         // Intentionally ignore. Prefer previous error.
13       }
14     }
15   }

从地点的代码中我们得以见到那多少个艺术有多个参数:

1.Reader reader:XML配置所在的文件流。

2.String environment:指定要履行的环境ID。

3.Properties properties:加载的变理音讯。

XMLConfigBuilder类的功能就是用来加载XML配置文件,也得以领略为读取。他的parse方法丰富的呈现出她的效劳来。

 1  public Configuration parse() {
 2     if (parsed) {
 3       throw new BuilderException("Each XMLConfigBuilder can only be used once.");
 4     }
 5     parsed = true;
 6     parseConfiguration(parser.evalNode("/configuration"));
 7     return configuration;
 8   }
 9 
10   private void parseConfiguration(XNode root) {
11     try {
12       Properties settings = settingsAsPropertiess(root.evalNode("settings"));
13       //issue #117 read properties first
14       propertiesElement(root.evalNode("properties"));
15       loadCustomVfs(settings);
16       typeAliasesElement(root.evalNode("typeAliases"));
17       pluginElement(root.evalNode("plugins"));
18       objectFactoryElement(root.evalNode("objectFactory"));
19       objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
20       reflectorFactoryElement(root.evalNode("reflectorFactory"));
21       settingsElement(settings);
22       // read it after objectFactory and objectWrapperFactory issue #631
23       environmentsElement(root.evalNode("environments"));
24       databaseIdProviderElement(root.evalNode("databaseIdProvider"));
25       typeHandlerElement(root.evalNode("typeHandlers"));
26       mapperElement(root.evalNode("mappers"));
27     } catch (Exception e) {
28       throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
29     }
30   }

从要下边的俩个章程中大家可以看来很熟练的代码字眼。相信不难看出就是加载各类节点上的音讯。事实上要是大家查阅一下parse方法的归来类型大家就可以领会这多少个手续末了就是为了扭转对应的Configuration类实例。可以这样子讲关于部署音讯加载最后一定都在Configuration类实例之中。所以查看Configuration类就变得很有意义。源码笔者就不贴出来占地点。

XMLConfigBuilder类源码里面有俩个位置是笔者相比较欣赏的。一个是大概封装了读取XML的操作类——XPathParser类。可能对此JAVA来讲这不算怎么。笔者从事过C#支出,所以感觉相比深吧。他只是做了一个简单的卷入。但是笔者看起来在读取XML便得越来越载顺心了——可读性更强了。

 public String evalString(Object root, String expression) {
    String result = (String) evaluate(expression, root, XPathConstants.STRING);
    result = PropertyParser.parse(result, variables);
    return result;
  }

  public Boolean evalBoolean(String expression) {
    return evalBoolean(document, expression);
  }

  public Boolean evalBoolean(Object root, String expression) {
    return (Boolean) evaluate(expression, root, XPathConstants.BOOLEAN);
  }

  public Short evalShort(String expression) {
    return evalShort(document, expression);
  }

地点是XPathParser类读取XML文件值各自需要调用的不二法门。大家可以通晓的可以领悟重返类型和调用的节点。笔者认为简约一小步,但是明理一大步。XMLConfigBuilder类源码里面还有一个作者觉得需要去注意学习的地点——MetaClass类。他的效率跟反射有涉及,同时用到ReflectorFactory类和Reflector类。他这规范封装之后用到反射效用便得愈加的容易领悟和冲天。过多的介绍还不如自己亲身去看一下体验一下。

好了,现在让我们回过头在来探视build方法最终回来什么才是最要害的。从源码中我们领略他回到的是一个DefaultSqlSessionFactory类型。

public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

本章的最紧要类出来了。当程序执行到下边的措施的时候,表明加载配置音讯的干活早已终结了。一个新的工作又要起头了。让我们在看一下作者的例子代码吧。

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
IProductMapper dao = session.getMapper(IProductMapper.class);

作者调用的远非参数的openSession方法。从这多少个方法里咱们可以看看她又去调用了一个叫openSessionFromDataSource的法门。那多少个办法才是结果和开端的连接点。

  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

上边的格局中有几个相比较紧要的类:Executor类、DefaultSqlSession类。其中专门是Executor类。本章就含混讲。后边会讲到。我们得以观望最终回到类是DefaultSqlSession类。对于数据库的增删改查就依靠那个类。

明朗著作到了此间就已经把接下去要去领会工作做了一个明明的不二法门——理解Executor类的效果。这规范我们就足以更进一步的刺探框架了。

网站地图xml地图