JDK中动态代理
- JDK只针对接口进行代理;要想对类进行实现代理可以使用:CGLIB,ASM等相关的操作字节码实现
- JDK中通过实现InvocationHandler接口,使用动态代理技术;
- 该接口需要实现invoke方法,Target类中被代理的方法,通过
Method.invoke
执行 - 同时,实现InvocationHandler的类,担任代理工厂角色,根据Target类实例化的对象,生成相应的动态代理类$Proxy0,同时创建相应的Proxy对象
- 创建的Proxy对象,其实现类,
实质是Target类的父类,和Target类有相同的方法声明,即实现共同的父类接口; - 通过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());
}
}
}
从上述源码可知:
- $Proxy0继承Proxy,实现了Service接口
- $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;
}