动态代理
代理的作用:控制和管理访问
代理的简单应用
package cn.future;
interface Interface {
void doSomething();
void doSomethingElse(String arg);
}
class RealObject implements Interface {
@Override
public void doSomething() {
System.out.println("do something");
}
@Override
public void doSomethingElse(String arg) {
System.out.println("somethingElse " + arg);
}
}
class SimpleProxy implements Interface {
private Interface procxied;
public SimpleProxy(Interface procxied) {
this.procxied = procxied;
}
@Override
public void doSomething() {
System.out.println("SimpleProxy doSomething");
procxied.doSomething();
}
@Override
public void doSomethingElse(String arg) {
System.out.println("SimpleProxy dosomethingElse");
procxied.doSomethingElse(arg);
}
}
public class SimpelProxyDemo{
public static void main(String[] args) {
consumer(new RealObject());
consumer(new SimpleProxy(new RealObject()));
}
public static void consumer(Interface inter){
inter.doSomething();
inter.doSomethingElse("bonobo");
}
}
动态代理简单应用
package cn.future;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("**** proxy: " + proxy.getClass() + ", method: " + method + ", args" + args);
if (args != null)
for (Object arg : args)
System.out.println(" " + arg);
return method.invoke(proxied, args);
}
public DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}
}
public class SimpleDynamicProxy {
public static void consumer(Interface iface) {
iface.doSomething();
iface.doSomethingElse("hello, future");
}
public static void main(String[] args) {
RealObject real = new RealObject();
consumer(real);
Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class.getClassLoader(),
new Class[]{Interface.class}, new DynamicProxyHandler(real));
consumer(proxy);
}
}
Proxy类提供创建代理类和实例的静态方法,也是所有由这些静态方法创建的类的父类。为某个接口Foo创建代理
InvocationHandler handler = new MyInvocationHandler(...);
Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
newInstance(handler);
或者简洁一点
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class<?>[] { Foo.class },
handler);
动态代理类(简称代理类
)是在运行时创建并实现了一系列具体的接口的类
,示例中
Interface为代理接口是代理类实现了的接口,代理实例是代理类的实例。每个代理实例均有一个与之相关的InvocationHandler实例。
注:
如果代理类实现的多个接口有相同的方法(方法名和签名都相同),会把实现的接口列表中的最前面包含该方法的Method对象传递给handler的invoke方法。
源码分析
首先看
Proxy创建代理类实例的方法
Proxy.newProxyInstance
/**
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
* handler. This method is equivalent to:
* <pre>
* Proxy.getProxyClass(loader, interfaces).
* getConstructor(new Class[] { InvocationHandler.class }).
* newInstance(new Object[] { handler });
* </pre>
*
* <p>{@code Proxy.newProxyInstance} throws
* {@code IllegalArgumentException} for the same reasons that
* {@code Proxy.getProxyClass} does.
*
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
* @throws IllegalArgumentException if any of the restrictions on the
* parameters that may be passed to {@code getProxyClass}
* are violated
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}, or
* if the invocation handler, {@code h}, is
* {@code null}
*/
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
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 {
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
// create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
return newInstance(cons, ih);
}
});
} else {
return newInstance(cons, ih);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
}
}
由文档注释可以看到,此方法等价于
Proxy.getProxyClass(loader, interfaces).
getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });
在第49行调用getProxyClass0()进行查询或者生成代理类。
通过设置
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
将会导出生成的代理类的.class文件,反编译可以得到代码如下:
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
final class $Proxy0 extends Proxy implements Interface {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m4;
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})).booleanValue();
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void doSomething() throws {
try {
super.h.invoke(this, m3, (Object[])null);//此处的h即为创建实例时传进来的InvocationHandler实例
} 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 void doSomethingElse(String var1) throws {
try {
super.h.invoke(this, m4, 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)).intValue();
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
m3 = Class.forName("Interface").getMethod("doSomething", new Class[0]);//此处通过反射进行获取接口方法
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m4 = Class.forName("Interface").getMethod("doSomethingElse", new Class[]{Class.forName("java.lang.String")});
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
将会导出生成的代理类的.class文件,反编译可以得到代码如下:由反编译代码可以看出,在进行对代理类的实现的方法doSomething进行调用时,会去调用传入的InvocationHandler的invoke方法。
动态代理及静态代理示例来自 书籍《Thinking in Java》
参考链接 JDK动态代理实现原理