为什么只用mapper接口就能运行sql? 而不需要接口的实现类.
在学习mybatis源码的时候, <深入浅出MyBatis技术原理与实战>书籍上看到了这一段,
为什么只用mapper接口就能运行sql(我们的接口没有创建实现类,为什么可以调用它的方法)?
主要是jdk动态代理技术, 我模拟了MyBatis的调用过程, 看完代码就可以理解这个问题了, 代码如下:
接口:
import java.util.Map;
public interface IExample {
public void setName(String name, int b);
public void setDesc(String description);
}
代理类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* 通过反射机制给接口(IExample)生成对象 / 模拟mybatis的执行流程.
*/
public class MyProxyView implements InvocationHandler {
public static Object newInstance(Class[] interfaces) {
return Proxy.newProxyInstance(MyProxyView.class.getClassLoader(),
interfaces, new MyProxyView());
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
//可以拿到方法的参数
Arrays.stream(args).forEach(System.out::println);
//这里不需要另外再次调用invoke方法, 就已经可以拿到接口方法了.
//也可以拿到其他东西.
/* String methodName = method.getName();
System.out.println("调用的方法名称为:" + methodName);
Class<?> returnType = method.getReturnType();
System.out.println("返回的类型为" + returnType.getName());*/
//也可以通过注解去取注解上的value
/* Annotation parameterAnnotations[][] = method.getParameterAnnotations();
for (int i = 0; i < parameterAnnotations.length; i++) {
for (Annotation annotation : parameterAnnotations[i]) {
if (Param.class.equals(annotation.annotationType())) {
Param o= ((Param) annotation);
String value = o.value();
System.out.println(value);
}
}
}*/
//!!!!!!!!!!!!!!这里很重要!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//最后,把这里拿到的参数和mapper.xml里的sql语句组合,用传统的jdbc执行.这样就可以操作数据库了.
Object parameters = null;
return parameters;
}
}
测试类:
package jichu.jdk动态代理;
public class MybatisExcuteDemoTest {
/**
* 类比于我们操作mapper接口:注入接口,执行方法.
*
* @param args
*/
public static void main(String[] args) {
// 这里不需要 IExample 的实现类.
IExample example = (IExample) MyProxyView.newInstance(new Class[]{IExample.class});
// 在接口执行的时候就会去调invoke 方法
example.setName("my example", 9);
example.setDesc("天气晴朗");
}
}
结果:
my example
9
天气晴朗