美文网首页
动态代理的实现与分析

动态代理的实现与分析

作者: 孔鹏飞 | 来源:发表于2022-09-19 14:16 被阅读0次

什么是动态代理?

代理模式(Proxy Pattern)是程序设计中的一种设计模式,定义为其他对象提供一种代理以控制对这个对象的访问。代理模式分为静态代理和动态代理,静态代理是手动创建或工具生成代理类的源码,动态代理则是在运行阶段动态生成代理类。

proxy-pattern.png

动态代理的实现

  1. 创建被代理的接口和实现类,Java中的动态代理基于接口
  2. 创建InvocationHandler接口的实现类,在invoke方法中实现代理逻辑
  3. 通过Proxy类的静态方法newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)创建代理对象
  4. 使用代理对象

创建被代理的接口

//Subject.java
public interface Subject {
    void hello(String str);
}

创建接口实现类

//RealSubject.java
public class RealSubject implements Subject {
    @Override
    public void hello(String str) {
        System.out.println("hello: " + str);
    }
}

创建InvocationHandler接口实现类


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

public class DynamicProxy implements InvocationHandler {

    private Object object;

    public DynamicProxy(Object object)
    {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable         
    {
        Object result=method.invoke(subject,args);
        return result;
    }
}

测试

RealSubject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxy(realSubject);
Subject subject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(), new Class<?>[] { Subject.class }, handler);
subject.hello("jack");

输出结果为hello: jack

动态代理原理分析

动态代理是通过Proxy类的newProxyInstance方法动态创建代理对象,然后将接口方法"委托"给InvocationHandler实例完成的,newProxyInstance方法的定义如下:

   public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
  • ClassLoader:接口类对应的ClassLoader
  • Class<?>[] :代理类要实现的接口列表
  • InvocationHandler: 方法调用处理类

对应的代码实现为:

    /**
     * Returns an instance of a proxy class for the specified interfaces
     * that dispatches method invocations to the specified invocation
     * handler.
     */
   @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<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            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);
        }
    }

核心代码如下:

  1. 找到代理类对于的Class
 Class<?> cl = getProxyClass0(loader, intfs);
  1. 通过反射获取代理类的构造函数,参数为InvocationHandler实例
 private static final Class<?>[] constructorParams =
      { InvocationHandler.class };
 final Constructor<?> cons = cl.getConstructor(constructorParams);
  1. 生成代理类的实例
return cons.newInstance(new Object[]{h});

生成的动态代理类如下:

//com.sun.proxy.$Proxy0.java
package com.sun.proxy;

import io.github.kongpf8848.pattern.proxy.Subject;
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 Subject {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    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 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 void hello(String var1) throws  {
        try {
            super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    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);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("io.github.kongpf8848.pattern.proxy.Subject").getMethod("hello", Class.forName("java.lang.String"));
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

在该代理类中,通过反射找到代理接口的hello方法,当调用代理类的hello方法时,委托InvocationHandler实例去处理。

相关文章

  • Java动态代理原理剖析(一)

    这篇文章将深入的分析Java的动态代理实现原理,首先将自己实现一个动态代理,然后顺势分析JDK中的动态代理实现并与...

  • AOP——cglib动态代理源码解析

    上一篇分析了使用JDK动态代理的低层实现原理,这次再来看看cglib实现动态代理的原理。 关于JDK动态代理的实现...

  • 代理

    来源:java动态代理实现与原理详细分析 代理模式是常用的java设计模式,他的特征是代理类与委托类实现同样的接口...

  • 编程常用的设计模式

    动态代理和静态代理 静态代理 动态代理 静态代理与动态代理的区别 JDK中的动态代理和CGLIB 实现动态代理的方...

  • 代理模式

    代理模式分静态代理与动态代理,而动态代理又在Spring中与两个实现:1.基于JDK的动态代理(通过接口实现)2....

  • Java面试之Java基础下册(含答案)

    15.动态代理与cglib实现的区别。 动态代理有两种实现方式,分别是:jdk动态代理和cglib动态代理 jdk...

  • java随笔(十一)

    java动态代理源码分析,总结。java动态代理实现步骤: 通过阅读源码发现,动态生成代理对象$Proxy0,该对...

  • AOP底层实现:cglib动态代理

    一.与JDK动态代理的区别: jdk动态代理:基于接口,实现接口中相同的方法去实现的;cglib动态代理:父子继承...

  • 动态代理的实现与分析

    什么是动态代理? 代理模式(Proxy Pattern)是程序设计中的一种设计模式,定义为其他对象提供一种代理以控...

  • 3.3AOP简介-第3章aop面向切面编程

    AOP:面向切面编程,底层采用动态代理实现的,采用了两种代理:jdk的动态代理与CGLIB的动态代理。AOP是动态...

网友评论

      本文标题:动态代理的实现与分析

      本文链接:https://www.haomeiwen.com/subject/iuqportx.html