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

一. 动态代理模式介绍

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

public interface Person {
    public void doSomething();

}
创建⼀个名为 Bob Person 接⼝的实现类,使其实现 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 的执⾏。 当我们使⽤ Configuration getMapper ⽅法时,会调⽤ 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、付费专栏及课程。

余额充值