原理分析Java Mybatis中的Mapper
程序员文章站
2022-03-07 15:07:54
目录准备1.pom文件2.user类-数据库3.实体类4.dao 层5.mapper 文件源码分析1.断点2.查看源码总结准备1.pom文件 &...
准备
1.pom文件
<dependencies> <!--mybatis坐标--> <dependency> <groupid>org.mybatis</groupid> <artifactid>mybatis</artifactid> <version>3.4.5</version> </dependency> <!--mysql驱动坐标--> <dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> <version>5.1.6</version> <scope>runtime</scope> </dependency> <!--单元测试坐标--> <dependency> <groupid>junit</groupid> <artifactid>junit</artifactid> <version>4.12</version> <scope>test</scope> </dependency> <!--日志坐标--> <dependency> <groupid>log4j</groupid> <artifactid>log4j</artifactid> <version>1.2.12</version> </dependency> <dependency> <groupid>org.projectlombok</groupid> <artifactid>lombok</artifactid> <version>1.18.2</version> <scope>provided</scope> </dependency> </dependencies>
2.user类-数据库
3.实体类
@getter @setter @tostring @noargsconstructor public class user { private int id; private string username; private string password; }
4.dao 层
public interface userdao { list<user> findall(); }
5.mapper 文件
<?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"> <mapper namespace="dao.userdao"> <select id="findall" resulttype="mode.user"> select * from user </select> </mapper>
核心配置文件
<?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> <!--通过properties标签加载外部properties文件--> <properties resource="jdbc.properties"></properties> <!--自定义别名--> <typealiases> <typealias type="mode.user" alias="user"></typealias> </typealiases> <!--数据源环境--> <environments default="developement"> <environment id="developement"> <transactionmanager type="jdbc"></transactionmanager> <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> <!--加载映射文件--> <mappers> <mapper resource="usermapper.xml"></mapper> </mappers> </configuration>
核心代码
import dao.userdao; import mode.user; import org.apache.ibatis.io.resources; import org.apache.ibatis.session.sqlsession; import org.apache.ibatis.session.sqlsessionfactory; import org.apache.ibatis.session.sqlsessionfactorybuilder; import java.io.ioexception; import java.io.inputstream; import java.util.list; public class testmapper { public static void main(string[] args) throws ioexception { //加载核心配置文件 inputstream resourceasstream = resources.getresourceasstream("sqlmapconfig.xml"); //获得sqlsession工厂对象 sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(resourceasstream); //获得sqlsession对象 sqlsession sqlsession = sqlsessionfactory.opensession(); //执行sql语句 userdao mapper = sqlsession.getmapper(userdao.class); list<user> userlist = mapper.findall(); //打印结果 system.out.println(userlist); //释放资源 sqlsession.close(); } }
源码分析
1.断点
2.查看源码
defaultsqlsession:
configuration:
这是configuration 类。我们主要看getmapper()方法
mapperregistry:
关键代码:mapperproxyfactory.newinstance(sqlsession);
mapperproxyfactory:
返回的是mapperproxy 对象
mapperproxy:
源码:
// source code recreated from a .class file by intellij idea // (powered by fernflower decompiler) // package org.apache.ibatis.binding; import java.io.serializable; import java.lang.invoke.methodhandles.lookup; import java.lang.reflect.constructor; import java.lang.reflect.invocationhandler; import java.lang.reflect.method; import java.util.map; import org.apache.ibatis.lang.usesjava7; import org.apache.ibatis.reflection.exceptionutil; import org.apache.ibatis.session.sqlsession; public class mapperproxy<t> implements invocationhandler, serializable { private static final long serialversionuid = -6424540398559729838l; private final sqlsession sqlsession; private final class<t> mapperinterface; private final map<method, mappermethod> methodcache; public mapperproxy(sqlsession sqlsession, class<t> mapperinterface, map<method, mappermethod> methodcache) { this.sqlsession = sqlsession; this.mapperinterface = mapperinterface; this.methodcache = methodcache; } public object invoke(object proxy, method method, object[] args) throws throwable { try { if (object.class.equals(method.getdeclaringclass())) { return method.invoke(this, args); } if (this.isdefaultmethod(method)) { return this.invokedefaultmethod(proxy, method, args); } } catch (throwable var5) { throw exceptionutil.unwrapthrowable(var5); } mappermethod mappermethod = this.cachedmappermethod(method); return mappermethod.execute(this.sqlsession, args); } private mappermethod cachedmappermethod(method method) { mappermethod mappermethod = (mappermethod)this.methodcache.get(method); if (mappermethod == null) { mappermethod = new mappermethod(this.mapperinterface, method, this.sqlsession.getconfiguration()); this.methodcache.put(method, mappermethod); } return mappermethod; } @usesjava7 private object invokedefaultmethod(object proxy, method method, object[] args) throws throwable { constructor<lookup> constructor = lookup.class.getdeclaredconstructor(class.class, integer.type); if (!constructor.isaccessible()) { constructor.setaccessible(true); } class<?> declaringclass = method.getdeclaringclass(); return ((lookup)constructor.newinstance(declaringclass, 15)).unreflectspecial(method, declaringclass).bindto(proxy).invokewitharguments(args); } private boolean isdefaultmethod(method method) { return (method.getmodifiers() & 1033) == 1 && method.getdeclaringclass().isinterface(); } }
在invoke方法中可以看到,如果我们调用的是object中的方法,不做任何处理,直接调用,否则执行:
mappermethod.execute(this.sqlsession, args);
mappermethod:
在mappermethod 中对sql语句进行分类反射
总结
- mapperproxyfactory中,使用jdk的动态代理生成mapper接口的代理代理类
- 由动态处理器mapperproxy中调用mappermethod中的方法处理执行sql
- 最后,在mappermethod中根据执行的方法返回值决定调用sqlsession中的对应方法执行sql
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容!
下一篇: 苹果通讯录怎么备份,掌握这个方法轻松备份
推荐阅读
-
Mybatis入门案例中设计模式的简单分析
-
Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析
-
Mybaits 源码解析 (六)----- 全网最详细:Select 语句的执行过程分析(上篇)(Mapper方法是如何调用到XML中的SQL的?)
-
[五]类加载机制双亲委派机制 底层代码实现原理 源码分析 java类加载双亲委派机制是如何实现的
-
Java中super关键字的详细分析
-
【Java】NIO中Selector的select方法源码分析
-
PHP中Session ID的实现原理分析
-
PHP中Session ID的实现原理实例分析
-
asp.net中利用ashx实现图片防盗链的原理分析
-
分析JAVA中几种常用的RPC框架