源码解析--mybatis mapper接口为啥没有实现类
泛域名ssl证书 239元1年送1个月、单域名39元1年,Sectigo(原Comodo证书)全球可信证书,强大的兼容性,高度安全性,如有问题7天内可退、可开发票
加微信VX 18718058521 备注SSL证书
【腾讯云】2核2G4M云服务器新老同享99元/年,续费同价
mybatis接口没有实现类,是如何实现功能的呢?
程序员都知道是mapper里面的接口名称和mapper.xml里面的名称一致,然后用的时候直接调用接口的方法就好了,但是里面具体的技术实现细节很多码农不一定懂,今天我就分析一下带领大家分析下具体实现原理。
1.加载配置文件创建SqlSession
public SqlSessionFactory getSqlSessionFactory() throws IOException { // 1.加载核心配置文件 InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); // 2.读取配置文件的内容 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = builder.build(inputStream); return sqlSessionFactory; }
如果是springboot项目,不需要此配置文件sqlMapConfig.xml,springboot启动时直接从yml配置文件中相关的mybats配置中加载相关xml和数据库连接配置。
启动时根据mapper.xml文件中的namespace来创建mapper对象(利用class.forname反射来生成类对象)
2.打开openSession
数据库连接信息mybatis会生成一个configuration类,此类里面会保存数据库连接信息
3.得到mapper对象
public void addUser() throws IOException { // 3.使用sqlSessionFactory对象,创建SqlSession对象,开启自动提交事务 SqlSession sqlSession = this.getSqlSessionFactory().openSession(true); // 调用方法执行 User user = new User(); //user.setId(4); user.setUsername("林诗音"); user.setBirthday(new Date()); user.setSex("女"); user.setAddress("来自大明朝"); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.addUser(user); //sqlSession.insert("com.test.mybatis.UserMapper.addUser", user); // 事务提交 // sqlSession.commit(); // 释放资源 sqlSession.close(); }
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
我们来分析这行代码,点进去如图
再进去如图,会出现一个 mapperProxyFactory 的类,而且是直接获取的,为啥呢,因为在启动的时候已经add进去了,根据配置文件xml,所以这里直接获取到 mapper代理工厂,然后调用代理工厂的newInstance方法
4.创建代理类
我们在往下看,
代码走到35行,我们看到new 了一个 mapperPorxy 的类,给他传入了mapper接口
然后代码走到31行,直接proxy类创建了一个newProxyInstance,并传入刚才创建的mapperProxy类
这里的话,我们需要复习下java动态代理的知识
我们在看看mapperProxy长啥样,如图,实现了InvocationHandler接口,我们知道实现InvocationHandler接口的类,被调用时会执行invoke方法,这些是java动态代理的知识,java动态代理只能用于接口,无法用于具体的类包括抽象类,因此这就是mybatis mapper中的接口只有接口没有实现类的原因。
那么啥时候执行invoke呢,就是在执行下面代码的时候
userMapper.addUser(user);
执行这行代码的时候会调用invoke,我们看看
MapperMethod mapperMethod = this.cachedMapperMethod(method);
mapperMethod 对象就是我们的mapper接口中的 addUser方法
return mapperMethod.execute(this.sqlSession, args);
args就是传入的实体对象,然后执行execute方法实现了操作数据库
5.XML中的SQL语句如何得到
也是从configuration.getMappedStatement(具体的方法名称)得到,sql有了,参数和实体也有了,就可以直接执行了
到此我们的分析基本结束,比较浅陋,但是基本流程大致如此,对了如果是springboot项目如何得到mapper对象呢,应该也是一样的,在我们的service层中的类中的 mapper接口字段,注解@Autowired时会被注入进去,咋么来的呢,当然是在启动的时候就已经添加进去了通过addmapper,所以不需要像单独mybatis 测试时的代码需要单独get才可以获取mapper。
好了,分析到此为止,有啥问题和建议,请私信或者公众号。欢迎大家关注我的公众号 【码农翻生】