一. 我写了一个Jdk动态代理类来测试jdk动态代理类的过程
- IRentingHouse rentingHouse = new RentingHouseImpl () ; // 委托对象---委托方
public class RentingHouseImpl implements IRentingHouse {
@Override
public void rentHosue () {
System.out.println ( "我要租用一室一厅的房子" ) ;
}
}
public interface IRentingHouse {
void rentHosue () ;
}
- 动态代理工厂中创建动态代理对象方法
/**
* Jdk动态代理
* @param obj 委托对象
* @return 代理对象
*/
public Object getJdkProxy ( Object obj ) {
// 获取代理对象
return Proxy.newProxyInstance( obj.getClass () .getClassLoader () , obj.getClass () .getInterfaces () ,
new InvocationHandler () {
@Override
public Object invoke ( Object proxy, Method method, Object [] args ) throws Throwable {
Object result = null;
// 写增强逻辑
System.out.println ( "中介(代理)收取服务费3000元" ) ;
// 调用原有业务逻辑
result = method.invoke ( obj,args ) ;
System.out.println ( "客户信息卖了3毛钱" ) ;
return result;
}
}) ;
}
- 保存 JDK 动态代理生产的类(能看到生成的动态代理对象)
/**
* 保存 JDK 动态代理生产的类
* @param filePath 保存路径,默认在项目路径下生成 $Proxy0.class 文件
*/
private static void saveProxyFile ( String... filePath ) {
if ( filePath.length == 0 ) {
System.getProperties() .put ( "sun.misc.ProxyGenerator.saveGeneratedFiles", "true" ) ;
} else {
FileOutputStream out = null;
try {
byte [] classFile = ProxyGenerator.generateProxyClass( "$Proxy0", RentingHouseImpl.class.getInterfaces ()) ;
out = new FileOutputStream ( filePath [ 0 ] + "$Proxy0.class" ) ;
out.write ( classFile ) ;
} catch ( Exception e ) {
e.printStackTrace () ;
} finally {
try {
if ( out != null ) {
out.flush () ;
out.close () ;
}
} catch ( IOException e ) {
e.printStackTrace () ;
}
}
}
}
- 入口
public static void main ( String [] args ) {
saveProxyFile() ;
IRentingHouse rentingHouse = new RentingHouseImpl () ; // 委托对象---委托方
// 从代理对象工厂获取代理对象
IRentingHouse jdkProxy = ( IRentingHouse ) ProxyFactory.getInstance() .getJdkProxy ( rentingHouse ) ;
jdkProxy.rentHosue () ;
}
二. 源码追踪
- Proxy.newProxyInstance()
- Class < ? > cl = getProxyClass0( loader, intfs ) ;
- proxyClassCache.get ( loader, interfaces ) ;==>V value = supplier.get () ;==>Objects.requireNonNull( valueFactory.apply ( key, parameter )) ;
- 代码进入java.lang.reflect.Proxy中的类ProxyClassFactory#apply()。
此类line.639行
byte [] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags ) ;
# 组装了一个byte类型代理类。在后面传了回去通过反编译
因此我们将byte [] proxyClassFile 反编译,则可以得到代理对象的类。在saveProxyFile中可以直接调用方法ProxyGenerator.generateProxyClass(),将反编译的类保存起来。
三.代理类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sun.proxy;
import designpattern.proxy.dynamicproxy.IRentingHouse;
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 IRentingHouse {
private static Method m1;
private static Method m3;
private static Method m2;
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});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void rentHosue() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} 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 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);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("designpattern.proxy.dynamicproxy.IRentingHouse").getMethod("rentHosue");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
可见:
public final class $Proxy0 extends Proxy implements IRentingHouse {
继承了Proxy,实现了IRentingHouse
结论分析:
因为JDK动态代理类已经继承了Proxy这个类,所以只能通过接口来与被代理类建立联系(两个类建立起联系,一是继承的关系【jdk已经不能通过这个方式了,因为java仅支持单继承】,另一种就是实现同一个接口【JDK动态代理选这种】),所以必须要求被代理类也得实现一个接口,这样的话代理类与被代理类就能通过这个接口建立联系了