JDK中动态代理

JDK中动态代理

  1. JDK只针对接口进行代理;要想对类进行实现代理可以使用:CGLIB,ASM等相关的操作字节码实现
  2. JDK中通过实现InvocationHandler接口,使用动态代理技术;
  3. 该接口需要实现invoke方法,Target类中被代理的方法,通过Method.invoke执行
  4. 同时,实现InvocationHandler的类,担任代理工厂角色,根据Target类实例化的对象,生成相应的动态代理类$Proxy0,同时创建相应的Proxy对象
  5. 创建的Proxy对象,其实现类,实质是Target类的父类,和Target类有相同的方法声明,即实现共同的父类接口;
  6. 通过Proxy对象,执行Target类统一声明的方法

相关代码如下:

父类接口:Service

package com.ocean.mode.proxy;

public interface Service
{
    public void sayHello();
    public void sayBye();
}

Target类:ServiceBean

package com.ocean.mode.proxy;

public class ServiceBean implements Service
{

    @Override
    public void sayHello()
    {
        // TODO Auto-generated method stub
        System.out.println("Hello");
    }

    public void sayBye()
    {
        // TODO Auto-generated method stub
        System.out.println("Bye");
    }

}

ProxyFactory类:ServiceProxy

package com.ocean.mode.proxy;

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

public class ServiceProxy implements InvocationHandler
{
    private Object targetObj;

    public Object createProxyIntance(Object targetObj)
    {
        this.targetObj = targetObj;
        return Proxy.newProxyInstance(this.targetObj.getClass().getClassLoader(),
            this.targetObj.getClass().getInterfaces(),
            this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable
    {
        System.out.println("\r\n执行前:---------------------");
        Object obj = method.invoke(this.targetObj, args);
        System.out.println("执行后:---------------------");
        return obj;
    }

}

ClientTest代码:

    /**
     * 代理模式
     */
    public static void proxy()
    {
        /* 设置此系统属性,让JVM生成的Proxy类写入文件.保存路径为:com/sun/proxy(如果不存在请手工创建) */
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        System.out.println(Proxy.getProxyClass(Service.class.getClassLoader(), Service.class));
        // 创建代理工厂对象
        ServiceProxy pro = new ServiceProxy();
        // 创建bean
        ServiceBean bean = new ServiceBean();
        // 创建代理
        Service service = (Service)pro.createProxyIntance(bean);

        // 打招呼说话!
        service.sayHello();

        service.sayBye();
    }

执行结果:

class com.sun.proxy.$Proxy0

执行前:---------------------
Hello
执行后:---------------------

执行前:---------------------
Bye
执行后:---------------------

JDK动态代理源码分析

从ClientTest中代码执行结果可以看出service对象所属类为com.sun.proxy.$Proxy0

com.sun.proxy.$Proxy0源码:

package com.sun.proxy;

import com.ocean.mode.proxy.Service;
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 Service {
    private static Method m1;
    private static Method m4;
    private static Method m2;
    private static Method m3;
    private static Method m0;

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

    public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (Error localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

    public final void sayHello()
    throws 
  {
    try
    {
      this.h.invoke(this, m4, null);
      return;
    }
    catch (Error localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

    public final String toString()
    throws 
  {
    try
    {
      return ((String)this.h.invoke(this, m2, null));
    }
    catch (Error localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

    public final void sayBye()
    throws 
  {
    try
    {
      this.h.invoke(this, m3, null);
      return;
    }
    catch (Error localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

    public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (Error localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m4 = Class.forName("com.ocean.mode.proxy.Service").getMethod("sayHello", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m3 = Class.forName("com.ocean.mode.proxy.Service").getMethod("sayBye", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            return;
        } catch (NoSuchMethodException localNoSuchMethodException) {
            throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
        } catch (ClassNotFoundException localClassNotFoundException) {
            throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
        }
    }
}

从上述源码可知:

  1. $Proxy0继承Proxy,实现了Service接口
  2. $Proxy0的构造方法,只是执行了Proxy类的构造方法,结合Proxy的源码来看:
    • 通过传入的InvocationHandler对象,也就ServiceProxy对象,初始化Proxy的h属性;
    • 调用h.invoke方法,也即是调用ServiceProxy.invoke方法;

综述:$Proxy0通过Proxy的属性h调用InvocationHandler.invoke方法,而InvocationHandler自身通过传入的method,args参数,利用反射执行Target中的目标方法

附录:Proxy部分源码

protected InvocationHandler h;

protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }

代理模式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值