文章目录
前言
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。应该是目前最火的ORM框架。它的实现原理非常简单。我以最简单的代码示例来帮助大家入门mybatis源码。
一、mybatis源码入门
在使用mybatis开发的时候,经常会有一个名为mapper
的包,里面的一般会有UserMapper
等这样的java类。例如:
@Repository
public interface UserMapper
{
@Select("select * from t_user where id=#{id}")
User selectById(Long id);
}
我们只需要定义一个接口,定义一些方法,通过注解或者xml写上sql语句,即可实现数据的查询。这种非常方便。mybatis通过动态代理帮助开发者创建实现类,大大提升了开发效率。其原理如下。
为了更加清晰,创建了一个纯净的maven工程。
创建Select
注解。对于mybatis的注解进行高仿。
package com;
import java.lang.annotation.*;
/**
* 2021/4/3.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Select {
String value();
}
创建mapper接口。
interface UserMapper{
@Select("select * from t_user where id=#{id}")
Object selectById(Long id);
}
对于开发者来说,一般在service中注入这个userMapper,并且调用selectById方法即可。
//@Autowired
UserMapper userMapper =(UserMapper) Proxy.newProxyInstance(MyBatisTest.class.getClassLoader(), new Class[]{UserMapper.class},new InvocationHandlerMy());
public void selectById(Long id){
userMapper.selectById(2L);
}
如上示例,一般service中由@Autowired
注解进行注入,因为此为纯净的工程没有@Autowired注解,这里可以通过jdk动态代理创建一个代理对象,最后调用selectById方法,调用之后的逻辑在InvocationHandlerMy
方法中进行实现。
class InvocationHandlerMy implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取调用方法的注解信息
Select annotation = method.getAnnotation(Select.class);
if(annotation!=null){
//获取注解的value。
//在Select的value存放的是sql信息
String value = annotation.value();
System.out.println(value);
//打印参数
System.out.println(Arrays.asList(args));
//创建连接
//执行sql
//封装对象
//关闭连接
}
return null;
}
}
打印结果:
select * from t_user where id=#{id}
[2]
在InvocationHandlerMy
中已经成功接收到了注解的信息和入参,这个时候就可以对sql自行处理。比如参数的替换,事务的处理等等。
另外sql中需要进行将#{id}替换为对应的参数,代码示例如下:
新增@Param
注解
package com;
import java.lang.annotation.*;
/**
* 2021/4/3.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface Param {
String value();
}
使用@Param
注解
interface UserMapper{
@Select("select * from t_user where id=#{id} and status=#{status}")
Object selectById(@Param("id") Long id,@Param("status")String status);
}
封装注解信息和对应的参数
//获取
public static Map<String, Object> getArgMap(Method method, Object[] args) {
Map<String, Object> argMap = new HashMap<String, Object>();
Parameter[] par = method.getParameters();
for(int i=0;i<par.length;i++){
Parameter p = par[i];
Param annotation = p.getAnnotation(Param.class);
String value = annotation.value();
argMap.put(value,args[i]);
}
return argMap;
}
//打印map
//{id=2, status=on}
获取了key-value对应关系之后,可以通过apache-commons-text工具类对sql的参数进行替换。
当然mybatis的功能特别多,它的源码也相对复杂一点,这只是展示了一下它最基本的思路,方便大家更加快速的学习他的源码。