前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[ORM] MyBatis 中是如何运用的代理模式的?

[ORM] MyBatis 中是如何运用的代理模式的?

作者头像
架构探险之道
发布2020-05-29 14:31:03
8440
发布2020-05-29 14:31:03
举报
文章被收录于专栏:架构探险之道架构探险之道

[ORM] MyBatis 中是如何运用的代理模式的?

简介

本文主要介绍设计模式之代理模式,并分析代理模式在 Mybatis 中是如何使用的?


静态代理动态代理源码分析深入动态代理源码小结获取更多

手机用户请横屏获取最佳阅读体验,REFERENCES中是本文参考的链接,如需要链接和更多资源,可以扫码加入『知识星球』(文末)获取长期知识分享服务。


静态代理

.

具体用户管理实现类

代码语言:javascript
复制
public class UserManagerImpl implements UserManager {
  @Override
  public void addUser(String userId, String userName) {
    System.out.println("UserManagerImpl.addUser");
  }
}

代理类

代码语言:javascript
复制
public class UserManagerImplProxy implements UserManager {
    // 目标对象
    private UserManager userManager;
    // 通过构造方法传入目标对象
    public UserManagerImplProxy(UserManager userManager){
        this.userManager=userManager;
    }
    @Override
    public void addUser(String userId, String userName) {
        try{
                //添加打印日志的功能
                //开始添加用户
                System.out.println("start-->addUser()");
                userManager.addUser(userId, userName);
                //添加用户成功
                System.out.println("success-->addUser()");
            }catch(Exception e){
                //添加用户失败
                System.out.println("error-->addUser()");
            }
    }

}

为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。

更通俗的说,代理解决的问题当两个类需要通信时,引入第三方代理类,将两个类的关系解耦,让我们只了解代理类即可,而且代理的出现还可以让我们完成与另一个类之间的关系的统一管理,但是切记,代理类和委托类要实现相同的接口,因为代理真正调用的还是委托类的方法。

动态代理

按照代理的创建时期,代理类可以分为两种:

静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。而动态:在程序运行时运用反射机制动态创建而成。

Java 动态代理创建:

  • 定义实现接口InvocationHandler
  • 调用(T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { interfaces }, h)

源码分析

先介绍几个核心对象

  • MapperProxyFactory
  • MapperProxy

分析

MapperProxyFactory

代码语言:javascript
复制
//Mapper 的代理工厂,用于创建Mapper的代理对象
public class MapperProxyFactory<T> {

  private final Class<T> mapperInterface;
  private final Map<Method, MapperMethodInvoker> methodCache = new ConcurrentHashMap<>();

  public MapperProxyFactory(Class<T> mapperInterface) {
    this.mapperInterface = mapperInterface;
  }

  public Class<T> getMapperInterface() {
    return mapperInterface;
  }

  public Map<Method, MapperMethodInvoker> getMethodCache() {
    return methodCache;
  }

  //JDK的动态代理
  @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<>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

}
//MapperProxy必须要实现InvocationHandler,用于代理方法执行时invoke进行增强调用
public class MapperProxy<T> implements InvocationHandler, Serializable {

  private static final long serialVersionUID = -4724728412955527868L;
  private static final int ALLOWED_MODES = Lookup.PRIVATE | Lookup.PROTECTED
      | Lookup.PACKAGE | Lookup.PUBLIC;
  private static final Constructor<Lookup> lookupConstructor;
  private static final Method privateLookupInMethod;
  private final SqlSession sqlSession;
  private final Class<T> mapperInterface;
  private final Map<Method, MapperMethodInvoker> methodCache;

  public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethodInvoker> methodCache) {
    this.sqlSession = sqlSession;
    this.mapperInterface = mapperInterface;
    this.methodCache = methodCache;
  }

  static {
    Method privateLookupIn;
    try {
      privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class, Lookup.class);
    } catch (NoSuchMethodException e) {
      privateLookupIn = null;
    }
    privateLookupInMethod = privateLookupIn;

    Constructor<Lookup> lookup = null;
    if (privateLookupInMethod == null) {
      // JDK 1.8
      try {
        lookup = Lookup.class.getDeclaredConstructor(Class.class, int.class);
        lookup.setAccessible(true);
      } catch (NoSuchMethodException e) {
        throw new IllegalStateException(
            "There is neither 'privateLookupIn(Class, Lookup)' nor 'Lookup(Class, int)' method in java.lang.invoke.MethodHandles.",
            e);
      } catch (Exception e) {
        lookup = null;
      }
    }
    lookupConstructor = lookup;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      //如果当前类直接时顶层父类,直接调用invoke方法
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else {
        //如果不是,获取方法的缓存,进行解析
        return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
  }

  private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
    try {
      return methodCache.computeIfAbsent(method, m -> {
        if (m.isDefault()) {
          try {
            if (privateLookupInMethod == null) {
              return new DefaultMethodInvoker(getMethodHandleJava8(method));
            } else {
              return new DefaultMethodInvoker(getMethodHandleJava9(method));
            }
          } catch (IllegalAccessException | InstantiationException | InvocationTargetException
              | NoSuchMethodException e) {
            throw new RuntimeException(e);
          }
        } else {
          return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
        }
      });
    } catch (RuntimeException re) {
      Throwable cause = re.getCause();
      throw cause == null ? re : cause;
    }
  }

  private MethodHandle getMethodHandleJava9(Method method)
      throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    final Class<?> declaringClass = method.getDeclaringClass();
    return ((Lookup) privateLookupInMethod.invoke(null, declaringClass, MethodHandles.lookup())).findSpecial(
        declaringClass, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()),
        declaringClass);
  }

  private MethodHandle getMethodHandleJava8(Method method)
      throws IllegalAccessException, InstantiationException, InvocationTargetException {
    final Class<?> declaringClass = method.getDeclaringClass();
    return lookupConstructor.newInstance(declaringClass, ALLOWED_MODES).unreflectSpecial(method, declaringClass);
  }

  interface MapperMethodInvoker {
    Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable;
  }

  private static class PlainMethodInvoker implements MapperMethodInvoker {
    private final MapperMethod mapperMethod;

    public PlainMethodInvoker(MapperMethod mapperMethod) {
      super();
      this.mapperMethod = mapperMethod;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
      return mapperMethod.execute(sqlSession, args);
    }
  }

  private static class DefaultMethodInvoker implements MapperMethodInvoker {
    private final MethodHandle methodHandle;

    public DefaultMethodInvoker(MethodHandle methodHandle) {
      super();
      this.methodHandle = methodHandle;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
      return methodHandle.bindTo(proxy).invokeWithArguments(args);
    }
  }
}

MapperRegistry

Mapper 的注册中心,所有解析的Mapper信息都存储在缓存中。

代码语言:javascript
复制
public class MapperRegistry {

  private final Configuration config;
  private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();

  public MapperRegistry(Configuration config) {
    this.config = config;
  }

  @SuppressWarnings("unchecked")
  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }

  public <T> boolean hasMapper(Class<T> type) {
    return knownMappers.containsKey(type);
  }

  //添加Mapper映射处理器到缓存
  public <T> void addMapper(Class<T> type) {
    if (type.isInterface()) {
      if (hasMapper(type)) {
        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
      }
      boolean loadCompleted = false;
      try {
        knownMappers.put(type, new MapperProxyFactory<>(type));
        // It's important that the type is added before the parser is run
        // otherwise the binding may automatically be attempted by the
        // mapper parser. If the type is already known, it won't try.
        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
        parser.parse();
        loadCompleted = true;
      } finally {
        if (!loadCompleted) {
          knownMappers.remove(type);
        }
      }
    }
  }

  /**
   * @since 3.2.2
   */
  public Collection<Class<?>> getMappers() {
    return Collections.unmodifiableCollection(knownMappers.keySet());
  }

  /**
   * @since 3.2.2
   */
  public void addMappers(String packageName, Class<?> superType) {
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
    for (Class<?> mapperClass : mapperSet) {
      addMapper(mapperClass);
    }
  }

  /**
   * @since 3.2.2
   */
  public void addMappers(String packageName) {
    addMappers(packageName, Object.class);
  }

}

.

查询流程图:Mapper映射处理器生成流程

代码语言:javascript
复制
sequenceDiagram
Title:Mapper映射处理器生成流程(class形式)
XMLConfigBuilder-->>XMLConfigBuilder:解析配置:parse
XMLConfigBuilder-->>XMLConfigBuilder:解析Mapper节点:mapperElement
XMLConfigBuilder-->>XMLConfigBuilder:判断加载类型,package、url、resource、class
XMLConfigBuilder-->>Configuration:添加Mapper:addMapper
Configuration-->>MapperRegistry:委托处理:addMapper
MapperRegistry-->>MapperProxyFactory:包裹new(type)
MapperRegistry-->>MapperRegistry: knownMappers.put(type, new MapperProxyFactory<>(type));

深入动态代理源码

.

核心组件 Proxy

代码语言:javascript
复制
@SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }
  • 核心方法:newProxyInstance
代码语言:javascript
复制
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    throws IllegalArgumentException
{
    Objects.requireNonNull(h);
        //安全校验
    final Class<?>[] intfs = interfaces.clone();
    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
    }

    /*
     * Look up or generate the designated proxy class.
     */
      //内存中生成Class定义
    Class<?> cl = getProxyClass0(loader, intfs);

    /*
     * Invoke its constructor with the designated invocation handler.
     */
    try {
        if (sm != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), cl);
        }
                //获取Class的构造函数
        final Constructor<?> cons = cl.getConstructor(constructorParams);
        final InvocationHandler ih = h;
        if (!Modifier.isPublic(cl.getModifiers())) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    cons.setAccessible(true);
                    return null;
                }
            });
        }
          //实例化对象
        return cons.newInstance(new Object[]{h});
    } catch (IllegalAccessException|InstantiationException e) {
        throw new InternalError(e.toString(), e);
    } catch (InvocationTargetException e) {
        Throwable t = e.getCause();
        if (t instanceof RuntimeException) {
            throw (RuntimeException) t;
        } else {
            throw new InternalError(t.toString(), t);
        }
    } catch (NoSuchMethodException e) {
        throw new InternalError(e.toString(), e);
    }
}
//getProxyClass0
/**
     * Generate a proxy class.  Must call the checkProxyAccess method
     * to perform permission checks before calling this.
     */
    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
      //类的接口数目限制  
      if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
          //优先从缓存拿代理对象的Class,没有的话通过ProxyClassFactory来创建
        return proxyClassCache.get(loader, interfaces);
    }
//proxyClassCache.get(loader, interfaces);
public V get(K key, P parameter) {
              //1. 从缓存读取代理对象的Class
        Objects.requireNonNull(parameter);

        expungeStaleEntries();

        Object cacheKey = CacheKey.valueOf(key, refQueue);

        // lazily install the 2nd level valuesMap for the particular cacheKey
        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
        if (valuesMap == null) {
            ConcurrentMap<Object, Supplier<V>> oldValuesMap
                = map.putIfAbsent(cacheKey,
                                  valuesMap = new ConcurrentHashMap<>());
            if (oldValuesMap != null) {
                valuesMap = oldValuesMap;
            }
        }

        // create subKey and retrieve the possible Supplier<V> stored by that
        // subKey from valuesMap
              //缓存没有的话就创建
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
        Supplier<V> supplier = valuesMap.get(subKey);
        Factory factory = null;

        while (true) {
            if (supplier != null) {
                // supplier might be a Factory or a CacheValue<V> instance
                V value = supplier.get();
                if (value != null) {
                    return value;
                }
            }
            // else no supplier in cache
            // or a supplier that returned null (could be a cleared CacheValue
            // or a Factory that wasn't successful in installing the CacheValue)

            // lazily construct a Factory
            if (factory == null) {
                factory = new Factory(key, parameter, subKey, valuesMap);
            }

            if (supplier == null) {
                supplier = valuesMap.putIfAbsent(subKey, factory);
                if (supplier == null) {
                    // successfully installed Factory
                    supplier = factory;
                }
                // else retry with winning supplier
            } else {
                if (valuesMap.replace(subKey, supplier, factory)) {
                    // successfully replaced
                    // cleared CacheEntry / unsuccessful Factory
                    // with our Factory
                    supplier = factory;
                } else {
                    // retry with current supplier
                    supplier = valuesMap.get(subKey);
                }
            }
        }
    }
  • 生成代理对象Class

.

代码语言:javascript
复制
//subKeyFactory.apply(key, parameter)
 private static final class ProxyClassFactory
        implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    {
        // prefix for all proxy class names
               //代理类名前缀
        private static final String proxyClassNamePrefix = "$Proxy";

        // next number to use for generation of unique proxy class names
        private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
              //校验接口
            for (Class<?> intf : interfaces) {
                /*
                 * Verify that the class loader resolves the name of this
                 * interface to the same Class object.
                 */
                Class<?> interfaceClass = null;
                try {
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {
                }
                if (interfaceClass != intf) {
                    throw new IllegalArgumentException(
                        intf + " is not visible from class loader");
                }
                /*
                 * Verify that the Class object actually represents an
                 * interface.
                 */
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
                }
                /*
                 * Verify that this interface is not a duplicate.
                 */
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
                }
            }

            String proxyPkg = null;     // package to define proxy class in
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            /*
             * Record the package of a non-public proxy interface so that the
             * proxy class will be defined in the same package.  Verify that
             * all non-public proxy interfaces are in the same package.
             */
            for (Class<?> intf : interfaces) {
                int flags = intf.getModifiers();
                if (!Modifier.isPublic(flags)) {
                    accessFlags = Modifier.FINAL;
                    String name = intf.getName();
                    int n = name.lastIndexOf('.');
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg;
                    } else if (!pkg.equals(proxyPkg)) {
                        throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                    }
                }
            }

            if (proxyPkg == null) {
                // if no non-public proxy interfaces, use com.sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            /*
             * Choose a name for the proxy class to generate.
             */
            long num = nextUniqueNumber.getAndIncrement();
              //拼接代理类名
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            /*
             * Generate the specified proxy class.
             */
              //生成Java字节码文件
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                  //创建Class对象
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                /*
                 * A ClassFormatError here means that (barring bugs in the
                 * proxy class generation code) there was some other
                 * invalid aspect of the arguments supplied to the proxy
                 * class creation (such as virtual machine limitations
                 * exceeded).
                 */
                throw new IllegalArgumentException(e.toString());
            }
        }
 }
//generateProxyClass

//defineClass0:本地方法
 private static native Class<?> defineClass0(ClassLoader loader, String name,
                                                byte[] b, int off, int len);

测试Class对象的输出

  • 定义代理对象和InvocationHandler
代码语言:javascript
复制
@AllArgsConstructor
@NoArgsConstructor
public class ProductHandler implements InvocationHandler {

    /**
     * 被代理对象
     */
    private ProductProcessor target;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("print Product Info!" + args[0].toString());
        System.out.println(">>>"+proxy.getClass().getSimpleName());
        return method.invoke(target, args);
    }
}

@Data
@ToString
public class Product {

    private String name;
}

public interface ProductProcessor {

    /**
     * 加工
     *
     * @param product
     */
    void processor(Product product);

}

public class ProxyTest {

    private static final String proxyClassNamePrefix = "$Proxy";

    public static void main(String[] args) {
        ClassGeneratorUtil.generateProxyClass(proxyClassNamePrefix+"0",new Class[]{ProductHandler.class});
    }

}
  • 定义输出class文件的方法
代码语言:javascript
复制
/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou Helios Dev, Ltd. All Right Reserved.
 * @address:     微信搜索公众号「架构探险之道」获取更多资源。
 * @date:        2020/5/24 11:58 下午
 * @description: 本内容仅限于编程技术学习使用,转发请注明出处.
 */
package com.yido.example.invoke;

import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;

/**
 * <p>
 *
 * </p>
 *
 * @author Helios
 * @date 2020/5/24 11:58 下午
 */
public class ClassGeneratorUtil {

    /**
     * 生成Class文件
     * @param proxyName
     * @param interfaces
     */
    public static void generateProxyClass(String proxyName, Class<?>[] interfaces) {
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces);
        String path = ClassGeneratorUtil.class.getResource(".").getPath();
        try (FileOutputStream fo = new FileOutputStream(path + proxyName + ".class")) {
            fo.write(proxyClassFile);
            fo.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 输出结果分析
代码语言:javascript
复制
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import com.yido.example.invoke.ProductHandler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements ProductHandler {
    private static Method m1;
    private static Method m8;
    private static Method m2;
    private static Method m3;
    private static Method m5;
    private static Method m4;
    private static Method m7;
    private static Method m9;
    private static Method m0;
    private static Method m6;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void notify() throws  {
        try {
            super.h.invoke(this, m8, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final Object invoke(Object var1, Method var2, Object[] var3) throws Throwable {
        //代理类的invoke方法被调用,使用父类的 InvocationHandler 变量,来完成代理方法的调用
        return (Object)super.h.invoke(this, m3, new Object[]{var1, var2, var3});
    }

    public final void wait(long var1) throws InterruptedException {
        try {
            super.h.invoke(this, m5, new Object[]{var1});
        } catch (RuntimeException | InterruptedException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final void wait(long var1, int var3) throws InterruptedException {
        try {
            super.h.invoke(this, m4, new Object[]{var1, var3});
        } catch (RuntimeException | InterruptedException | Error var5) {
            throw var5;
        } catch (Throwable var6) {
            throw new UndeclaredThrowableException(var6);
        }
    }

    public final Class getClass() throws  {
        try {
            return (Class)super.h.invoke(this, m7, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void notifyAll() throws  {
        try {
            super.h.invoke(this, m9, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void wait() throws InterruptedException {
        try {
            super.h.invoke(this, m6, (Object[])null);
        } catch (RuntimeException | InterruptedException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m8 = Class.forName("com.yido.example.invoke.ProductHandler").getMethod("notify");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.yido.example.invoke.ProductHandler").getMethod("invoke", Class.forName("java.lang.Object"), Class.forName("java.lang.reflect.Method"), Class.forName("[Ljava.lang.Object;"));
            m5 = Class.forName("com.yido.example.invoke.ProductHandler").getMethod("wait", Long.TYPE);
            m4 = Class.forName("com.yido.example.invoke.ProductHandler").getMethod("wait", Long.TYPE, Integer.TYPE);
            m7 = Class.forName("com.yido.example.invoke.ProductHandler").getMethod("getClass");
            m9 = Class.forName("com.yido.example.invoke.ProductHandler").getMethod("notifyAll");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m6 = Class.forName("com.yido.example.invoke.ProductHandler").getMethod("wait");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
  • 代码执行测试
代码语言:javascript
复制
public class ProxyTest {

    private static final String proxyClassNamePrefix = "$Proxy";

    public static void main(String[] args) {
        //ClassGeneratorUtil.generateProxyClass(proxyClassNamePrefix+"0",new Class[]{ProductHandler.class});
        Product product = new Product();
        product.setName("苹果iPhone SE");
        //创建被代理对象
        DefaultProductProcessor defaultProductProcessor = new DefaultProductProcessor();
        //生成代理对象
        ProductProcessor processor = (ProductProcessor) Proxy.newProxyInstance(defaultProductProcessor.getClass().getClassLoader(),
                defaultProductProcessor.getClass().getInterfaces(), new ProductHandler(defaultProductProcessor));
        //执行代理对象的方法
        processor.process(product);
    }

}
//日志
print Product Info!Product(name=苹果iPhone SE)
>>>$Proxy0

调用链路

代码语言:javascript
复制
sequenceDiagram
Title:动态代理
ProductProcessor->>Proxy:生成代理类newProxyInstance
ProductProcessor->>ProductProcessor:process
ProductProcessor->>$Proxy0:m3: ProductHandler.invoke(Object,Method,Object2)
$Proxy0->>Proxy:super.h.invoke(this, m3, new Object[]{var1, var2, var3})
Proxy->>ProductHandler:method(process):invoke
ProductHandler->>ProductHandler:invoke,并进行代理修饰操作
ProductHandler ->> ProductHandler:proxy参数为代理类$Proxy0,对应上文传入的var1

.

在这里插入图片描述

小结

  • JDK动态代理的核心角色:被代理类(实现类)、接口、实现InvocationHandler的触发管理类。
  • 启动初期,便会解析配置,生成所有预处理数据,绑定每一个statement,在缓存中保存对应的接口信息。
  • 获取Mapper对象的过程,实质是获取一个动态代理对象。这个代理类会继承Proxy类,实现被代理的接口,里面持有了一个MapperProxy的触发管理类。
  • 动态代理本质上是利用自定义接口进行方法申明,利用InvocationHandler进行代理修饰的定义,通过invoke方法进行代理对象的调用,代理对象本生也会生成对应的Class文件,存储在内存或硬盘中。

.

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构探险之道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • [ORM] MyBatis 中是如何运用的代理模式的?
    • 静态代理
      • 动态代理
        • 源码分析
          • 深入动态代理源码
            • 小结
            相关产品与服务
            微服务引擎 TSE
            微服务引擎(Tencent Cloud Service Engine)提供开箱即用的云上全场景微服务解决方案。支持开源增强的云原生注册配置中心(Zookeeper、Nacos 和 Apollo),北极星网格(腾讯自研并开源的 PolarisMesh)、云原生 API 网关(Kong)以及微服务应用托管的弹性微服务平台。微服务引擎完全兼容开源版本的使用方式,在功能、可用性和可运维性等多个方面进行增强。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档