MyBatis源码笔记(一) -- 大致流程

测试代码如下:

//获得资源文件流mybatis-config.xml
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
reader.close();
//创建一个SqlSession
SqlSession sqlSession = sessionFactory.openSession();
//获得接口代理类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userMapper.xxxx;//开始调用
1 创建SqlSessionFactory

1.1 加载配置文件

SqlSessionFactoryBuilder类

public SqlSessionFactory build(Reader reader) {
   	return build(reader, null, null);
}

public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
      return build(parser.parse());
    } catch...
	 finally {
      ...
        reader.close();
      ...
    }
}

XMLConfigBuilder类

public XMLConfigBuilder(Reader reader, String environment, Properties props) {
	//构造一个需要验证,XMLMapperEntityResolver的XPathParser
  	this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
}

public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
   commonConstructor(validation, variables, entityResolver);
	//加载XML文件为document对象
   this.document = createDocument(new InputSource(inputStream));
}

XMLMapperEntityResolver主要用于避免联网获取验证文件

上面调用了重载的构造函数

private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
    //首先调用父类初始化Configuration
    super(new Configuration());
    //错误上下文设置成SQL Mapper Configuration(XML文件配置),以便后面出错了报错用吧
    ErrorContext.instance().resource("SQL Mapper Configuration");
    //将Properties全部设置到Configuration里面去
    this.configuration.setVariables(props);
    this.parsed = false;
    this.environment = environment;
    this.parser = parser;
 }

Configuration类是所有配置的装载类,贯穿mybatis的执行流程

1.2 解析配置文件

回顾下上面,在创建好XMLConfigBuilder后就要进行解析:

	XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
	return build(parser.parse());

XMLConfigBuilder类

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
      //1.properties
      propertiesElement(root.evalNode("properties"));
      //2.类型别名
      typeAliasesElement(root.evalNode("typeAliases"));
      //3.插件
      pluginElement(root.evalNode("plugins"));
      //4.对象工厂
      objectFactoryElement(root.evalNode("objectFactory"));
      //5.对象包装工厂
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      //6.设置
      settingsElement(root.evalNode("settings"));
      // read it after objectFactory and objectWrapperFactory issue #631
      //7.环境
      environmentsElement(root.evalNode("environments"));
      //8.databaseIdProvider
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      //9.类型处理器
      typeHandlerElement(root.evalNode("typeHandlers"));
      //10.映射器
      mapperElement(root.evalNode("mappers"));
    } catch...
}

最终解析结果都会放进Configuration对象里,最终返回给上一层

1.3 创建SqlSessionFactory实例

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

可以看到返回的是DefaultSqlSessionFactory

2 创建SqlSession

DefaultSqlSessionFactory类

public SqlSession openSession() {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}


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);
      //然后产生一个DefaultSqlSession
      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();
    }
}

可以看到最后返回的是DefaultSqlSession实例。

3 获取接口代理类

DefaultSqlSession类

public <T> T getMapper(Class<T> type) {
    //最后会去调用MapperRegistry.getMapper
    return configuration.<T>getMapper(type, this);
}

Configuration类

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
}

MapperRegistry类

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw...
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch...
}

最终是通过Configuration中的MapperRegistry成员根据指定class获取MapperProxyFactory这个工厂类来实例出一个代理类,MapperRegistry在解析XML配置文件的时候就会把需要代理的接口包装成MapperProxyFactory缓存起来。

最后附上网上的一张结构图
Mybatis Frame

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
将SSM框架中的MyBatis升级到MyBatis-Plus是可行的,可以实现共存。SSM框架由Spring、Spring MVC和MyBatis组成,而MyBatis-Plus是对MyBatis的增强扩展。下面将介绍如何将它们共存。 首先,需要将MyBatis升级到MyBatis-Plus。可以将MyBatis-Plus的依赖项添加到项目的pom.xml文件中,替换原有的MyBatis依赖。然后,需要对原有的MyBatis配置文件进行修改。MyBatis-Plus提供了一些方便的功能和特性,如自动填充、逻辑删除等,可以根据项目需求选择开启或关闭。 在SSM框架中,MyBatis-Plus可以与原有的Spring框架和Spring MVC框架完美共存。Spring框架负责管理和配置各种Bean,MyBatis-Plus可以与Spring框架一起使用,将其作为DAO层的组件进行管理。在Spring的配置文件中,可以将MyBatis-Plus的配置文件加入到配置中。 在Spring MVC框架中,可以继续使用原有的控制器、服务和视图解析器等组件。MyBatis-Plus可以与Spring MVC框架无缝集成,通过Spring MVC接收请求,然后调用MyBatis-Plus进行数据访问和处理。 在具体开发过程中,可以利用MyBatis-Plus提供的一些特性简化开发工作。例如,可以使用MyBatis-Plus的代码生成器来自动生成DAO、实体类和Mapper等代码,减少手动编写的工作量。 总结来说,将SSM框架中的MyBatis升级到MyBatis-Plus是完全可以实现的,它们可以共存并完美集成。通过使用MyBatis-Plus,我们可以更加便捷地开发和管理数据库操作,提高开发效率和代码质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值