Mybatis解析——Configuration

本文详细解析了MyBatis配置文件mybatis-config.xml的内容及Configuration的创建过程,介绍了XMLConfigBuilder如何通过解析mybatis-config.xml生成Configuration实例,并解析了mybatis配置文件中的各个元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    从之前的《Mybatis解析——SqlSessionFactoryBean》可以看出,Configuration在SqlSessionFactory的创建过程中是一个很重要的环节。

    在SqlSessionFactoryBean.class可以看到Configuration的创建方式,在未配置configurationProperties的情况下,这里主要的参数是configLocation.getInputStream(),就是mybatis配置文件的路径:即mybatis-config.xml

    mybatis-config.xml如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="callSettersOnNulls" value="true"/>
        <!--<setting name="logImpl" value="STDOUT_LOGGING" />-->
        <setting name="defaultStatementTimeout" value="40"/>
    </settings>

    <typeAliases>
        <typeAlias alias="PYunYingECPMRecord" type="me.ele.vas.cpt.server.model.PYunYingECPMDto"/>

    </typeAliases>

</configuration>
xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), (String)null, this.configurationProperties);
configuration = xmlConfigBuilder.getConfiguration();

XMLConfigBuilder中,通过super()初始化来一个Configuration实例。

private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
    super(new Configuration());
    this.localReflectorFactory = new DefaultReflectorFactory();
    ErrorContext.instance().resource("SQL Mapper Configuration");
    this.configuration.setVariables(props);
    this.parsed = false;
    this.environment = environment;
    this.parser = parser;
}

mybatis-config.xml文件解析

xmlConfigBuilder.parse();

private void parseConfiguration(XNode root) {
    try {
        this.propertiesElement(root.evalNode("properties"));
        Properties settings = this.settingsAsProperties(root.evalNode("settings"));
        this.loadCustomVfs(settings);
        this.typeAliasesElement(root.evalNode("typeAliases"));
        this.pluginElement(root.evalNode("plugins"));
        this.objectFactoryElement(root.evalNode("objectFactory"));
        this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
        this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
        this.settingsElement(settings);
        this.environmentsElement(root.evalNode("environments"));
        this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
        this.typeHandlerElement(root.evalNode("typeHandlers"));
        this.mapperElement(root.evalNode("mappers"));
    } catch (Exception var3) {
        throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
    }
}

XNode封装了Node,XPathParser是xml文件的解析工具类


### MyBatis底层实现原理 MyBatis 的底层实现主要可以划分为以下几个部分:配置解析、动态代理机制以及 JDBC 封装。以下是对其具体实现过程的详细分析: #### 配置解析 (Configuration Parsing) 在 Spring Boot 整合 MyBatis 时,`MybatisAutoConfiguration` 类起到了关键作用。它通过扫描 `@MapperScan` 注解或者默认路径下的 Mapper 接口文件,将其注册为 Bean 定义[^1]。这些 Bean 定义会被存储到容器中的 `BeanDefinitions` 中,从而使得每个 Mapper 接口都能被正确识别并初始化。 ```java @Configuration @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionTemplate.class }) @EnableConfigurationProperties(MybatisProperties.class) public class MybatisAutoConfiguration { @Autowired(required = false) private List<Interceptor> interceptors; public MybatisAutoConfiguration(DataSource dataSource) { this.dataSource = dataSource; } @Bean(name = "sqlSessionFactory") @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory() throws Exception { ... } } ``` 上述代码片段展示了如何通过自动配置类完成对 MyBatis 的初始化工作,并将相关组件注入到 Spring 容器中。 --- #### 动态代理机制 (Dynamic Proxy Mechanism) 当一个 Mapper 接口被调用时,实际上返回的是由 MyBatis 创建的一个代理对象。这个代理对象是由 `MapperProxyFactory` 负责生成的。每次调用 Mapper 方法时,都会触发该工厂内的 `getObject()` 方法来创建具体的代理实例[^2]。 ```java public T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance( mapperProxy.getClass().getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) { try { return method.invoke(this, args); } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } return sqlSession.<M>selectOne(mapperMethod.command.getName(), mapperMethod.paramMap); } ``` 以上代码说明了 MyBatis 如何利用 Java 的动态代理功能拦截方法调用,并最终映射至 SQL 执行逻辑上。 --- #### JDBC 封装 (JDBC Encapsulation) 为了简化开发者操作数据库的过程,MyBatis 对标准 JDBC API 进行了一层抽象处理。所有的 CRUD 操作都集中于 `SqlSession` 上面进行管理。这不仅隐藏了许多繁琐细节,还提供了事务支持等功能[^4]。 ```java try(SqlSession session = factory.openSession()) { Blog blog = session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101); } catch(Exception e){ log.error(e.getMessage()); } ``` 此示例演示了如何借助 `SqlSession` 实现数据查询任务的同时保持资源的安全释放。 --- ### 总结 综上所述,MyBatis 的底层设计围绕着三大核心模块展开——即 **配置解析**、**动态代理机制** 和 **JDBC 封装**。这种架构既保证了框架本身的灵活性,又极大地降低了使用者的学习成本和技术门槛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值