MyBatis运行原理

    xiaoxiao2023-10-21  154

    原理

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

    读取配置文件缓存到Configuration对象中,用于创建SqlSessionFactorySqlSession的执行过程

    构建SqlSessionFactory过程

    通过 org.apache.ibatis.builder.xml.XMLConfigBuilder 解析配置的XML文件,读出所配置的参数,并将读取的内容存入 org.apache.ibatis.session.Configuration 类对象中。而Configuration采用的是单例模式,几乎所有的MyBatis配置内容都会存放在这个单例对象中。使用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)的封装返回处理的,不经常使用。

    最新回复(0)