第一步:
动态代理的使用。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class TestProxy {
public static void main(String[] args) {
/*这是newProxyInstance必须的参数,因此先按照格式来写
* 并且InvocationHandler是一个接口,必须要实现invoke方法,即被代理方法的什么时候调用。
*/
InvocationHandler handler = new MyInvocationHandler(new Test());
/*
* 主要查看这个方法。
*/
Math math = (Math)Proxy.newProxyInstance(Math.class.getClassLoader(), Test.class.getInterfaces(), handler);
/*
* 显示的调用方法。
*/
math.add(2, 3);
}
}
interface Math{
public void add(int a,int b);
}
class Test implements Math{
@Override
public void add(int a, int b) {
System.out.println("result:" + a + b);
}
}
class MyInvocationHandler implements InvocationHandler{
Math math;
public MyInvocationHandler(Math math) {
this.math = math;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法被调用!"+proxy.getClass().getMethods());
Object object = method.invoke(math, args);
System.out.println("方法结束!");
return object;
}
}
第二步:
查看源码。
//源码,可以使用ctrl然后点击方法查看。
//@CallSensitive用来找到真正发起反射请求的类,防止双重反射,至于双重反射,则不太清楚。
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{ //查看h是否为空,为空则抛出NullPointerException
Objects.requireNonNull(h);
//clone直接创建了一个新(属性与老对象相同)的对象
final Class<?>[] intfs = interfaces.clone();
//关于java安全性能代码,与本代码基本无关
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
//检查创建代理类所需的权限。
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
//这里比较重要,查找或生成指定的代理类。
/*
* Look up or generate the designated proxy class.
*/
/*
这里维护了一个static final的缓存,如果intfs长度超过65535个,就抛出异常
如果缓存里面存在相应的类,就获取,如果不存在,就使用ProxyClassFactory创建类
*/
//得到了一个public $Proxy0的一个返回
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//这段代码,将InvocationHandler填入到代理类的构造器参数中
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
//判断生成的代码是否为public类
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);
}
}
第三步:
查看生成的.class文件
由于自己找太过于麻烦了,找了一下别人生成的代码
/*
* Decompiled with CFR 0_110.
*
* Could not load the following classes:
* com.sun.proxy.$Proxy0
* ctgu.bytecode.proxy.service.HelloService
*/
package com.sun.proxy;
import ctgu.bytecode.proxy.service.HelloService;
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 HelloService {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler invocationHandler) {
super(invocationHandler);
}
public final boolean equals(Object object) {
try {
return (Boolean)this.h.invoke((Object)this, m1, new Object[]{object});
}
catch (Error | RuntimeException v0) {
throw v0;
}
catch (Throwable var2_2) {
throw new UndeclaredThrowableException(var2_2);
}
}
public final String sayHello(String string) {
try {
return (String)this.h.invoke((Object)this, m3, new Object[]{string});
}
catch (Error | RuntimeException v0) {
throw v0;
}
catch (Throwable var2_2) {
throw new UndeclaredThrowableException(var2_2);
}
}
public final String toString() {
try {
return (String)this.h.invoke((Object)this, m2, null);
}
catch (Error | RuntimeException v0) {
throw v0;
}
catch (Throwable var1_1) {
throw new UndeclaredThrowableException(var1_1);
}
}
public final int hashCode() {
try {
return (Integer)this.h.invoke((Object)this, m0, null);
}
catch (Error | RuntimeException v0) {
throw v0;
}
catch (Throwable var1_1) {
throw new UndeclaredThrowableException(var1_1);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("ctgu.bytecode.proxy.service.HelloService").getMethod("sayHello", Class.forName("java.lang.String"));
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException var1) {
throw new NoSuchMethodError(var1.getMessage());
}
catch (ClassNotFoundException var1_1) {
throw new NoClassDefFoundError(var1_1.getMessage());
}
}
}
总结:
1、生成的代理类,继承自Proxy,实现了被代理类的接口。
2、将invocationHandler作为参数传入构造器中。
3、生成equals,toString(),hashCode(),以及被代理类的接口方法。
4、在各个方法中,直接调用构造器生成的invocationHandler的invoke方法。
5、Proxy的三个参数:
(1)类加载器,由于我们是对某一个接口代理,所以必须要是接口的类加载器。
(2)被代理的类的接口,这主要用于代理类的生成
(3)invocationHandler,这个我也不知道怎么翻译,但是,这个参数会被传入代理类的构造器中。
6、invocationHandler的三个参数:
(1)代理类对象,在代理类的代码中,为this,即当前对象
(2)方法,在代理类生成的过程中,通过反射获取到相应的方法。
(3)参数列表,表示(2)方法中需要的参数。