动态代理模式的介绍及在MyBatis框架中的体现

本文介绍了Java动态代理模式,通过一个Person接口和Bob实现类展示了JDK动态代理的使用。动态代理在Mybatis中扮演关键角色,使得我们只需定义Mapper接口,Mybatis会在后台自动执行SQL。文章详细解释了Mybatis如何利用动态代理实现Mapper接口的调用,将方法转发到MapperProxy的invoke方法,进而执行SQL操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 动态代理模式介绍

代理模式(Proxy Pattern):给某⼀个对象提供⼀个代理,并由代理对象控制对原对象的引⽤。代理模式 的英⽂叫做Proxy,它是⼀种对象结构型模式,代理模式分为静态代理和动态代理,我们来介绍动态代理。
举例:
创建⼀个抽象类,Person接⼝,使其拥有⼀个没有返回值的doSomething⽅法。
package com.lagou.dynamicproxy;

public interface Person {
    public void doSomething();

}
创建⼀个名为BobPerson接⼝的实现类,使其实现doSomething⽅法
package com.lagou.dynamicproxy;

public class Bob implements Person {

    @Override
    public void doSomething() {
        System.out.println("Bob doing Something");
    }
}
创建JDK动态代理类,使其实现InvocationHandler接⼝。拥有⼀个名为target的变量,并创建 getTa rget获取代理对象⽅法
package com.lagou.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKDynamicProxy implements InvocationHandler {

    // 声明被代理的对象
    private Person person;

    //构造函数
    public JDKDynamicProxy(Person person) {
        this.person = person;
    }

    //获取代理对象
    public Object getTarget(){
        Object proxyInstance = Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this);

        return proxyInstance;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("对原方法进行了前置增强");
        //原方法执行
        Object invoke = method.invoke(person, args);
        System.out.println("对原方法进行了后置增强");
        return invoke;
    }
}
创建JDK动态代理测试类J DKDynamicTest
package com.lagou.dynamicproxy;

public class proxyTest {
    public static void main(String[] args) {

        System.out.println("不使用代理类,调用doSomething");
        Person person = new Bob();
        person.doSomething();

        System.out.println("--------------------------");

        System.out.println("使用代理类,调用doSomething");
        Person proxy = (Person) new JDKDynamicProxy(new Bob()).getTarget();
        proxy.doSomething();



    }
}

二. 模式在Mybatis中实现:

代理模式可以认为是Mybatis的核⼼使⽤的模式,正是由于这个模式,我们只需要编写Mapper.java接 ⼝,不需要实现,由Mybati s后台帮我们完成具体SQL的执⾏。当我们使⽤ConfigurationgetMapper⽅法时,会调⽤mapperRegistry.getMapper⽅法,⽽该⽅法⼜ 会调⽤ mapperProxyFactory.newInstance(sqlSession)来⽣成⼀个具体的代理:
public class MapperProxyFactory<T> {
 private final Class<T> mapperInterface;
 private final Map<Method, MapperMethod> methodCache = new
 ConcurrentHashMap<Method, MapperMethod>();
 public MapperProxyFactory(Class<T> mapperInterface) {
 this.mapperInterface = mapperInterface;
 }
 public Class<T> getMapperInterface() {
 return mapperInterface;
 }
 public Map<Method, MapperMethod> getMethodCache() {
 return methodCache;
 @SuppressWarnings("unchecked")
 protected T newInstance(MapperProxy<T> mapperProxy) {
 return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new
 Class[] { mapperInterface },
 mapperProxy);
 }
 public T newInstance(SqlSession sqlSession) {
 final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession,
mapperInterface, methodCache);
 return newInstance(mapperProxy);
 }
 }
在这⾥,先通过T newInstance(SqlSession sqlSession)⽅法会得到⼀个MapperProxy对象,然后调⽤TnewInstance(MapperProxy mapperProxy)⽣成代理对象然后返回。⽽查看MapperProxy的代码,可以看到如下 内容:
public class MapperProxy<T> implements InvocationHandler, Serializable {
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws
 Throwable {
 try {
 if (Object.class.equals(method.getDeclaringClass())) {
 return method.invoke(this, args);
 } else if (isDefaultMethod(method)) {
 return invokeDefaultMethod(proxy, method, args);
 }
 } catch (Throwable t) {
 throw ExceptionUtil.unwrapThrowable(t);
 }
 final MapperMethod mapperMethod = cachedMapperMethod(method);
 return mapperMethod.execute(sqlSession, args);
 }
⾮常典型的,该MapperProxy类实现了InvocationHandler接⼝,并且实现了该接⼝的invoke⽅法。通 过这种⽅式,我们只需要编写Mapper.java接⼝类,当真正执⾏⼀个Mapper接⼝的时候,就会转发给 MapperProxy.invoke⽅法,⽽该⽅法则会调⽤后续的sqlSession.cud>executor.execute>prepareStatement ⼀系列⽅法,完成 SQL 的执⾏和返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值