一、demo
Tom找中介租房
- 1.首先,定义一个接口HouseRenting类,表示租房这个共同的行为
public interface HouseRenting {
void rent();
}
-
- 被代理类Tom,表示要实现的行为,Tom要租房
public class Tom implements HouseRenting {
@Override
public void rent() {
System.out.println("Tom want to rent a house");
}
}
- 3.代理类JDKProxyHandler
public class JDKProxyHandler implements InvocationHandler {
private Object object;
public JDKProxyHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//before
System.out.println("带Tom看房前-到达约定地点");
Object invoke = method.invoke(object, args);
//after
System.out.println("带Tom看房后-签合同");
return invoke;
}
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}
}
- 4.测试方法
public class Main {
public static void main(String[] args) {
Tom tom = new Tom();
JDKProxyHandler handler = new JDKProxyHandler(tom);
HouseRenting proxy = (HouseRenting) handler.getProxy();
proxy.rent();
}
}
- 5.输出结果
带Tom看房前-到达约定地点
Tom want to rent a house
带Tom看房后-签合同
二、看源码
- 6.生成$Proxy0.class方法
public class JdkProxySourceClass {
public static void main(String[] args) {
byte[] classFile = ProxyGenerator.generateProxyClass("$proxy0", new Class[]{HouseRenting.class});
FileOutputStream fos = null;
try {
fos = new FileOutputStream("/Users/test/$Proxy0.class");
fos.write(classFile);
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
-
- $Proxy0.class部分代码
public final class $proxy0 extends Proxy implements HouseRenting {
private static Method m3;
//构造方法通过调用父类Proxy.class的构造方法,给成员变量invocationHandler赋值
public $proxy0(InvocationHandler var1) throws {
super(var1);
}
//调用父类中的成员变量InvocationHandler 的 invoke ()方法
public final void rent() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
//static代码块中创建了被代理类的方法
m3 = Class.forName("proxy.staticproxy.HouseRenting").getMethod("rent");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
-
- Java动态代理实现原理
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
/*
* Look up or generate the designated proxy class.
*通过类加载器和接口生成代理类
*cl值为:class com.sun.proxy.$Proxy0
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*调用特定的构造器
*cons值为:public com.sun.proxy.$Proxy0(java.lang.reflect.InvocationHandler)
*/
try {
final Constructor<?> cons = cl.getConstructor(constructorParams);
//反射创建实例
return cons.newInstance(new Object[]{h});
- 9.getProxyClass0方法通过接口创建类
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
-
- 上一个步骤中的proxyClassCache.get的缓存值最终会从调用ProxyClassFactory#apply获取值
{
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
}
可以发现, 用于产生代理类字节码的代码是:ProxyGenerator.generateProxyClass,接着再调用native的defineClass0加载字节码生成类对象。