JDK动态代理
jdk动态代理是基于接口的,也就是说被代理的类必须实现某个接口。接下来详细介绍一下jdk动态代理使用流程,首先给出一张jdk动态代理类图:
- 实现InvocationHandler接口
InvocationHandler接口中只有一个接口方法invoke(Object proxy, Method method, Object[] args)。
proxy:代理对象
method:被代理方法
args:被代理方法参数列表
实现InvocationHandler接口的目的是在接口方法中对被代理方法进行增强。代码清单如下:
public class DynamicProxy implements InvocationHandler {
private Object target; //目标对象
public DynamicProxy(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("主方法执行前");
//使用反射调用被代理方法
method.invoke(target, args);
System.out.println("主方法执行后");
return null;
}
}
- 使用Proxy类来生成代理对象
Proxy类中有一个静态方法newProxyInstance,该方法的作用是根据接口生成代理对象。同时,Proxy还有一个InvocationHandler属性
loader | 类加载器 |
---|---|
interfaces | 接口 |
h | 处理器,及步骤1中创建的对象 |
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;
}
});
}
//使用自定义的InvocationHandler对象来实例化代理类
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);
}
}
- 代理类文件
代理类继承了Proxy
public final class $Proxy0 extends Proxy implements IJdbc {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m5;
private static Method m6;
private static Method m0;
private static Method m4;
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);
}
}
//代理方法实际上是调用的InvocationHandler对象的invoke方法,在该方法中,对被代理方法进行了增强
public final void add() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void delete() throws {
try {
super.h.invoke(this, m5, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void select() throws {
try {
super.h.invoke(this, m6, (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 update() throws {
try {
super.h.invoke(this, m4, (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("com.dynamicProxy.jdk.IJdbc").getMethod("add");
m5 = Class.forName("com.dynamicProxy.jdk.IJdbc").getMethod("delete");
m6 = Class.forName("com.dynamicProxy.jdk.IJdbc").getMethod("select");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m4 = Class.forName("com.dynamicProxy.jdk.IJdbc").getMethod("update");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
- 总结
综上所述,jdk动态代理是通过继承Proxy类,实现被代理接口的方式实现的。在Proxy类中有一个InvocationHandler对象,在该对象中,对被代理类进行增强,生成的代理类实际上是调用父类中的InvocationHandler处理器的invoke方法来实现代理功能的。由于代理类必须实现Proxy类,又由于java是单继承的,因此jdk动态代理只能代理接口