MyBatis运行原理

原理

MyBatis的运行过程分为两大步:

  1. 读取配置文件缓存到Configuration对象中,用于创建SqlSessionFactory
  2. SqlSession的执行过程
    在这里插入图片描述
构建SqlSessionFactory过程
  1. 通过 org.apache.ibatis.builder.xml.XMLConfigBuilder 解析配置的XML文件,读出所配置的参数,并将读取的内容存入 org.apache.ibatis.session.Configuration 类对象中。而Configuration采用的是单例模式,几乎所有的MyBatis配置内容都会存放在这个单例对象中。
  2. 使用Configuration对象创建SqlSessionFactory。MyBatis中的SqlSessionFactory是一个接口,不是一个实现类,所以MyBatis提供了一个默认的实现类 org.apache.ibatis.session.defaults.DefaultSqlSessionFactory。在大部分的情况下没必要自己去创建SqlSessionFactory的实现类,这种创建方式就是一种Builder模式。

XMLConfigBuilder中解析XML方法源码:

public class XMLConfigBuilder extends BaseBuilder {
	......................
	public Configuration parse() {
	    if (parsed) {
	      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
	    }
	    parsed = true;
	    parseConfiguration(parser.evalNode("/configuration"));
	    return configuration;
	}
	private void parseConfiguration(XNode root) {
	    try {
	      propertiesElement(root.evalNode("properties")); //issue #117 read properties first
	      typeAliasesElement(root.evalNode("typeAliases"));
	      pluginElement(root.evalNode("plugins"));
	      objectFactoryElement(root.evalNode("objectFactory"));
	      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
	      settingsElement(root.evalNode("settings"));
	      environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631
	      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);
	    }
	}
	............................
}

我们可以看到它是通过一个一个节点的解析XML的内容得到对应的信息,最后构建出一个Configuration对象。
有了Configuration对象,就可以通过SqlSessionFactoryBuilder的build方法构建SqlSessionFactory对象

public class SqlSessionFactoryBuilder {
	...................
	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.
	      }
	    }
  }
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
  .......................
}
SqlSession执行过程

有了SqlSessionFactory对象就可以轻易的获取SqlSession,SqlSession也是个接口,给出了查询、插入、更新、删除的方法。

public class DefaultSqlSessionFactory implements SqlSessionFactory {
	..................
	public SqlSession openSession() {
    	return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  	}
  	..................
}
Mapper的动态代理

SqlSession中提供了一个getMapper方法,例如:

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

源码:

public class DefaultSqlSession implements SqlSession {
	............................
	public <T> T getMapper(Class<T> type) {
   		return configuration.<T>getMapper(type, this);
  	}
	............................
}
public class Configuration {
	................
	public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
	    return mapperRegistry.getMapper(type, sqlSession);
	}
	.................
}
public class MapperRegistry {
	  private Configuration config;
	  private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();
	
	  public MapperRegistry(Configuration config) {
	    this.config = config;
	  }
	
	  @SuppressWarnings("unchecked")
	  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
	    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
	    if (mapperProxyFactory == null)
	      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
	    try {
	      return mapperProxyFactory.newInstance(sqlSession);
	    } catch (Exception e) {
	      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
	    }
	  }
	  ...........................................
}

可以很明显的看出,它运用到了Configuration对象的getMapper方法获取对应的接口对象,又运用了映射器的注册器Mapperregistry获取对应的接口对象。首先会判断是否注册一个Mapper,如果没有则抛出异常信息,如果有就会启用MapperProxyFactory工厂生成一个代理实例。

SqlSession的四大对象
  • Executor代表执行器,由它调度StatementHandler、ParameterHandler、ResultSetHandler等来执行对应的SQL,其中StatementHandler是最重要的。
  • StatementHandler的作用是使用数据库的Statement(PreparedStatement)执行操作,它是四大对象的核心,起到承上启下的作用,许多插件都是通过拦截它来实现的。
  • ParameterHandler是用来处理SQL参数的。
  • ResultSetHandler是进行数据集(ResultSet)的封装返回处理的,不经常使用。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值