MyBatis(三)动态代理

本文介绍了MyBatis中的动态代理机制,包括代理模式的概念、JDK动态代理和CGLib动态代理的工作原理。详细分析了JDK动态代理的源码,并探讨了MyBatis如何利用动态代理创建Mapper接口的代理对象,以及Mapper接口方法的执行流程。
摘要由CSDN通过智能技术生成

  在介绍MyBatis动态代理前。我们先介绍一下什么是代理模式。

代理模式

      代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。

      代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性。

代理模式结构图

动态代理

      代理模式分为两种:静态代理和动态代理。静态代理是程序编译阶段确定代理类,而动态代理是在程序运行时确定代理类,代理类在程序运行时创建的代理方式被成为动态代理,动态代理是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。

JDK自带的动态代理方式(必须有接口)

先实现一个接口和具体的实现类
#####接口
```
public interface IUser {
    void talk();
}
```
#####实现类
```
public class User implements IUser {
    @Override
    public void talk() {
        System.out.println("doing User.talk");
    }
}
```
要是先动态代理,首先创建一个实现InvocationHandler这个接口的类
```
public class UserProxy implements InvocationHandler {
     private Object object;
     public UserProxy(Object object){
         super();
         this.object = object;
     }
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         System.out.println("doing UserProxy.invoke");
         method.invoke(object, args);
         System.out.println("doing UserProxy.invoke end");
         return null;
     }
     /**
      * 实现InvocationHandler接口要重写invoke方法,方法的三个参数分别:
      * proxy:就是动态代理生成的代理类对象
      * method:就是调用的方法
      * args:表示该方法的参数
      */
}
```
在main函数中创建代理对象,通过该对象,调用委托类的方法,每个方法的调用JVM都会给我们调用上面实现
InvocationHandler接口的类对象的invoke方法
```
public static void main(String[] args) {
     IUser user = (IUser) Proxy.newProxyInstance(ProxyDemo.class.getClassLoader(), new Class[]{IUser.class}, new UserProxy(new User()));
     user.talk();
}
```
输出结果
```
doing UserProxy.invoke
doing User.talk
doing UserProxy.invoke end
```

JDK动态代理原理

      main中调用了代码user.talk()方法后,JVM会帮助自动实现invoke调用呢?在上面main添加一个监控

public static void main(String[] args) {
     //可以查看JDK生成的动态代理类
     System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
     IUser user = (IUser) Proxy.newProxyInstance(ProxyDemo.class.getClassLoader(), new Class[]{IUser.class}, new UserProxy(new User()));
     user.talk();
}

     生成一个$Proxy().class文件,代理类的源码,public final class $Proxy0 extends Proxy implements IUser$Proxy()的定义,确实实现了IUser接口,和代理模式下的代理类完全一样,因此当user.talk()调用时,根据JAVA的多态原理,调用的应该是代理对象$Prox

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值