文章目录
深入探索MyBatis的动态代理模式
引言
在Java开发中,MyBatis作为一个半自动的ORM(对象关系映射)框架,被广泛应用于数据持久层。它通过简单的API和灵活的配置,使得数据库操作变得简洁而高效。MyBatis的核心特性之一是动态代理模式,它允许我们通过接口而非具体的实现类来操作数据库。本文将深入探讨MyBatis动态代理的内部机制和实现原理。
一、 MyBatis动态代理概述
动态代理是一种设计模式,它在运行时创建代理对象,以控制对某个对象的访问。MyBatis的动态代理模式允许开发者定义一个Mapper接口,而无需提供实现类。MyBatis会在运行时自动创建这个接口的代理对象,代理对象会拦截接口方法的调用,并执行相应的数据库操作。
动态代理的优势
- 解耦数据库操作和业务逻辑:通过接口定义数据库操作,使业务逻辑与数据访问分离。
- 提高代码的可维护性:接口的变更不会影响业务逻辑,只需调整Mapper接口或XML配置。
- 简化数据访问代码:避免了重复编写大量的数据访问代码,如开关事务、处理SQL语句等。
二、准备工作
文件存放结构视图
1、Mybatis的主配置文件 mybatis-config.xml
mybatis-config.xml主要用来配置mybatis的运行环境,数据源、事务等。
在classpath下创建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>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<!-- 可以配置多个environment -->
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/shopdb" />
<property name="username" value="root" />
<property name="password" value="123" />
</dataSource>
</environment>
</environments>
</configuration>
2、db.properties文件:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
3、mybatis-config.xml引用properties文件:
<!-- 加载properties文件 -->
<properties resource="db.properties"></properties>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<!-- 可以配置多个environment -->
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
三、MyBatis动态代理的实现原理
1. Mapper接口定义
首先,定义一个Mapper接口,声明需要执行的数据库操作方法:
public interface UserMapper {
User getUserById(int id);
void insertUser(User user);
// 更多数据库操作方法...
}
2. XML映射文件
然后,创建一个XML映射文件,将Mapper接口中的方法与SQL语句关联起来:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace命名空间,作用就是对sql进行分类管理
注意:使用mapper代理方法开发时,namespace需要特殊设置
-->
<mapper namespace="com.example.mapper.UserMapper">
<select id="getUserById" resultType="com.example.model.User">
SELECT * FROM users WHERE id = #{id}
</select>
<!-- 更多SQL映射配置... -->
</mapper>
注意:sql语句的id必须和接口中对应方法名称一致才能关联起来
3. 将sql映射文件添加到MyBatis主配置文件中
mybatis框架需要加载映射文件,将UserMapper.xml添加到mybatis-config.xml中
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
4. 创建SqlSessionFactory
使用MyBatis的配置文件和XML映射文件,创建一个SqlSessionFactory
:
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
5. 获取Mapper代理对象
通过SqlSession
获取Mapper接口的代理对象:
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
6. 调用代理对象方法
调用Mapper代理对象的方法,MyBatis会拦截这些调用,并执行相应的数据库操作:
User user = userMapper.getUserById(1);
四、MyBatis动态代理的内部机制
MyBatis使用JDK的动态代理机制来实现Mapper接口的代理对象。当调用getMapper
方法时,MyBatis会检查是否已经为该接口创建了代理对象。如果没有,它会使用Proxy.newProxyInstance
方法创建一个代理对象,该对象实现了Mapper接口,并拦截所有方法调用。
代理对象的invoke
方法会根据方法的签名找到对应的SQL语句,并执行。这是通过MapperMethod
实现的,它将接口方法与XML映射文件中的SQL语句关联起来。
五、结论
MyBatis的动态代理模式提供了一种声明式的数据访问方式,它简化了数据库操作,并提高了代码的可维护性。通过理解MyBatis动态代理的实现原理,我们可以更加灵活地使用这个强大的框架来处理复杂的数据访问需求。