mybatis接口式编程原理

众所周知,mybatis实现了接口式编程,简化了我们Dao层的编写,通过定义一个接口和XMl文件即可实现对数据库sql的执行。那它是怎么现实的呢,其实是利用了java的动态代理。
我们先聊聊动态代理模式:
代理模式:对原有功能,进行增强
一、静态代理: 构成--->1.抽象接口 2.目标对象3.代理对象
重新定义一个类继承这接口,并定义此接口的引用,用来引用目标对象,调用原方法
public abstract class AbstractObject {
public abstract void operation();
}

目标对象角色
public class RealObject extends AbstractObject {
@Override
public void operation() {
//一些操作
System.out.println("一些操作");
}
}

代理对象角色
public class ProxyObject extends AbstractObject{
RealObject realObject = new RealObject();
@Override
public void operation() {
//调用目标对象之前可以做相关操作
System.out.println("before");
realObject.operation();
//调用目标对象之后可以做相关操作
System.out.println("after");
}
}

客户端
public class Client {
public static void main(String[] args) {
AbstractObject obj = new ProxyObject();
obj.operation();
}

}

二、动态代理:每个类都存在虚拟的class代理类,只存在于内存中
public class ProxyDemo {
public static void main(String[] args) {
//目标对象
final Dao demoDao = new DemoDao();
//接口Dao的代理类的代理对象
Dao dao = (Dao)Proxy.newProxyInstance(ProxyDemo.class.getClassLoader(),
new Class[]{Dao.class}, //指定代理接口
new InvocationHandler() {//拦截代理对象的所有方法。

@Override //proxy代表代理对象本身 method 调用哪个方法,引用哪个方法对象
//args调用方法的参数封装成对象装进数组
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//System.out.println(method.getName()+" "+Arrays.toString(args));
//1.增强的功能
System.out.println("-----有方法进入,拦截到的方法为-----");
//2.调用目标对象原有的方法
//method.invoke(demoDao, args);
return null;
}
});
//System.out.println(dao); tostring方法被拦截,一直返回null
//System.out.println(dao.getClass());
//dao.add(10, 20);
dao.equals("abc");

}
}

下面说明下mybatis是怎么利用动态代理来现实接口式编程的,首先在mybatis中只定义了接口,如果需要调用接口中的方法必须要有现实类对象,利用动态代理来创建实现类对象:
MapperProxy implements InvocationHandler 覆写类里invoke()方法 --> Proxy.newProxyInstance(类加载器,接口.class数组,MapperProxy对象)-->sql Session.getMapper(接口.class) == Proxy.newProxyInstance()--> IMessage imessage = Proxy.newProxyInstance()
imessage.queryMessageList == MapperProxy.invoke();

根据上面的流程,Proxy.newProxyInstance() 创建了代理对象,可以把它看做接口的实现类对象,MapperProxy 拦截了代理对象的所有方法,就是说代理对象执行什么方法都会进入到invoke()方法中,这就有个实现类对象

下面说说代理对象执行接口中的方法,为什么可以执行xml中配置的sql,这个就涉及接口式编程的规则了,也是为什么要设置这些规则的原因。
加载mybatis配置信息configuratioon,也就加载了Mapper的xml信息-->因为接口全名称.方法名=namespace.id-->所以MapperProxy.invoke()中有这样的代码:sqlSession.selectList(namespace.id,parameter) 根据返回值类型决定用selectOne还是selectList

这样当我们用代理对象调用接口中方法时,就会在Mapper.invoke()方法中,执行sqlSession.selectList方法,也就是imessage.queryMessageList(parameter) = sqlSession.selectList(namespace.id,parameter),也就执行我们xml中的sql,这也是为什么我们namespace必须要是接口的完全限定名,而sql的id必须和接口中方法名一致的原因。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值