一,JDK動态代理
在純手寫動态代理前,首先分析一套标準JDK動态代理的執行流程。
1,目标類頂層接口
public interface ProxyInterface {
public void targetMethod();
}
2,目标類
public class JDKProxyTarget implements ProxyInterface{
@Override
public void targetMethod() {
System.out.println("代理方法...");
}
}
3,代理類
public class JDKProxy {
private ProxyInterface proxyInterface;
public JDKProxy(ProxyInterface proxyInterface) {
this.proxyInterface = proxyInterface;
}
public Object instanceProxy() {
System.out.println("代理方法開始...");
ProxyInterface instance = (ProxyInterface) Proxy.newProxyInstance(
proxyInterface.getClass().getClassLoader(),
proxyInterface.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(proxyInterface, args);
System.out.println("代理方法結束...");
return null;
}
});
return instance;
}
}
4,測試類
public class JDKProxyTest {
public static void main(String[] args) throws Exception {
JDKProxy proxy = new JDKProxy(new JDKProxyTarget());
ProxyInterface proxyInterface = (ProxyInterface) proxy.instanceProxy();
System.out.println(proxyInterface.getClass());
proxyInterface.targetMethod();
}
}

5,代碼解析
a,Proxy.newInstance()方法
* 第一個參數為目标類的類加載器
* 第二個參數為目标類的接口集合,JDK動态代理目标類必須實作一個接口,這是為了保證生成的代理類和目标類之前的強一緻性關系
* 第三個參數為InvocationHandler接口的實作類,這裡直接通過匿名内部類實作,重寫了invoke方法
b,InvocationHandler接口實作類
* 實作該類必須重寫invoke()方法,動态代理實作在代理類中該接口的實作類調用該方法,并在該方法中反射執行該方法完成整個動态代理流程;
* 第一個參數為生成的動态代理對象;
* 第二個參數為動态代理在用戶端執行的方法;
* 第三個參數為該方法的參數清單;
* 通過反射來完成方法調用;
c,通過a步驟後,JDK會虛拟生成一個$Proxy0類,該類也實作了目标類實作的接口,進而多态傳回該虛拟類對象,可以通過代碼輸出該類
* 代碼
public class JDKProxyTest {
public static void main(String[] args) throws Exception {
JDKProxy proxy = new JDKProxy(new JDKProxyTarget());
ProxyInterface proxyInterface = (ProxyInterface) proxy.instanceProxy();
System.out.println(proxyInterface.getClass());
proxyInterface.targetMethod();
byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{ProxyInterface.class});
FileOutputStream outputStream = new FileOutputStream("E:\\$Proxy0.class");
outputStream.write(bytes);
outputStream.close();
}
}
* $Proxy0類 --- 生成為.class檔案,直接通過IDEA進行反編譯
public final class $Proxy0 extends Proxy implements ProxyInterface {
private static Method m1;
private static Method m2;
private static Method m3;
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 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 targetMethod() throws {
try {
super.h.invoke(this, m3, (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)).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")});
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("com.gupao.designpattern.proxy.jdk.ProxyInterface").getMethod("targetMethod", new Class[0]);
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());
}
}
}
d, 可以看到該虛拟類繼承Proxy類并實作了目标類頂層接口,并反射擷取了目标類中的所有方法的Method對象;
e, 同時,虛拟類也同時重寫了目标類的所有方法,并通過下列方式進行調用
super.h.invoke(this, m3, (Object[])null);
super : 指該代理類的超類,也就是Proxy;
h : 點進源碼可以看到這樣一行聲明
protected InvocationHandler h;
在虛拟類的構造器中,也擷取了InvocationHandler的引用,是以,這裡的h,指的也就是在匿名内部類定義的實作類對象;
h.invoke():就是調用匿名内部類中重寫的invoke()方法,分别傳遞參數該對象(this),執行的方法(method),方法參數(null);
二,手寫動态代理步驟分析
從上面标準的JDK動态流程可以看出,手寫動态代理,需要這樣幾個類
1,SelfProxy類,定義newInstance()方法,進行代理對象建立
* 在該方法中首先需要輸出代理類的.java檔案
* 編譯該.java檔案生成.class檔案
* 通過類加載器加載該.class檔案
* 生成該.class檔案的事例對象作為代理對象傳回
2,SelfInvocationHandler接口,定義invoke()方法,在代理類中進行目标方法調用
* 在.java檔案中,定義構造器,傳遞該類引用
* 通過SelfInvocationHandler實作類對象調用invoke()方法,實作代理方式的方法調用
3,SelfClassloader,自定義類加載器,繼承JDK的ClassLoader類,實作自定義的加載方式
4,SelfJDKProxy,實作SelfInvocationHandler接口,重寫invoke()方法,實作最終方法運作
三,手寫動态代理代碼實作
1,目标類頂層接口
public interface SelfProxyInterface {
public void targetMethod();
}
2,目标類
public class SelfJDKProxyTarget implements SelfProxyInterface{
@Override
public void targetMethod() {
System.out.println("代理方法...");
}
}
3,SelfClassLoader類 -- 自定義類加載器,加載.class到JVM記憶體中
public class SelfClassLoader extends ClassLoader{
private File classPathFile;
public SelfClassLoader() {
String classPath = SelfClassLoader.class.getResource("").getPath();
this.classPathFile = new File(classPath);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String className = SelfClassLoader.class.getPackage().getName() + "." + name;
if (null != classPathFile) {
File classFile = new File(classPathFile, name + ".class");
if (classFile.exists()) {
FileInputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(classFile);
out = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int len;
while((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
return defineClass(className, out.toByteArray(), 0, out.size());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != in) {
in.close();
}
if (null != out) {
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return null;
}
}
4,SelfProxy類 -- 生成虛拟代理類,建立代理對象
public class SelfProxy {
private static final String ENTER = "\r\n";
public static Object newInstance(SelfClassLoader classLoader, Class<?>[] interfaces, SelfInvocationHandler h) {
try {
// 動态生成源代碼
String srcClass = generateSrc(interfaces);
// 輸出Java檔案
String filePath = SelfProxy.class.getResource("").getPath() + "$ProxyO.java";
System.out.println(filePath);
FileWriter fileWriter = new FileWriter(filePath);
fileWriter.write(srcClass);
fileWriter.flush();
fileWriter.close();
// 編譯Java檔案為class檔案
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable iterable = fileManager.getJavaFileObjects(filePath);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, iterable);
task.call();
fileManager.close();
// 加載編譯生成的class檔案到JVM
Class<?> proxyClass = classLoader.findClass("$ProxyO");
Constructor<?> constructor = proxyClass.getConstructor(SelfInvocationHandler.class);
// 删掉虛拟代理類
File file = new File(filePath);
file.delete();
// 傳回位元組碼重組以後的代理對象
return constructor.newInstance(h);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String generateSrc(Class<?>[] interfaces) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("package com.gupao.designpattern.proxy.self;" + ENTER + ENTER);
stringBuilder.append("import com.gupao.designpattern.proxy.jdk.ProxyInterface;" + ENTER);
stringBuilder.append("import java.lang.reflect.Method;" + ENTER);
stringBuilder.append("public class $ProxyO implements " + interfaces[0].getName() + "{" + ENTER);
stringBuilder.append("SelfInvocationHandler h;" + ENTER);
stringBuilder.append("public $ProxyO(SelfInvocationHandler h) {" + ENTER);
stringBuilder.append("this.h = h;" + ENTER);
stringBuilder.append("}" + ENTER);
for (Method method : interfaces[0].getMethods()) {
stringBuilder.append("public " + method.getReturnType().getName() + " " + method.getName() + "() {" + ENTER);
stringBuilder.append("try {" + ENTER);
stringBuilder.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + method.getName() + "\", new Class[]{});" + ENTER);
stringBuilder.append("this.h.invoke(this, m, null);" + ENTER);
stringBuilder.append("} catch(Throwable able) {" + ENTER);
stringBuilder.append("able.getMessage();" + ENTER);
stringBuilder.append("}" + ENTER);
stringBuilder.append("}" + ENTER + ENTER);
}
stringBuilder.append("}" + ENTER);
return stringBuilder.toString();
}
}
該類代碼的具體步驟在注釋中已經寫明;
5,檢視生成的.java檔案
package com.gupao.designpattern.proxy.self;
import com.gupao.designpattern.proxy.jdk.ProxyInterface;
import java.lang.reflect.Method;
public class $ProxyO implements com.gupao.designpattern.proxy.self.SelfProxyInterface {
SelfInvocationHandler h;
public $ProxyO(SelfInvocationHandler h) {
this.h = h;
}
public void targetMethod() {
try {
Method m = com.gupao.designpattern.proxy.self.SelfProxyInterface.class.getMethod("targetMethod", new Class[]{});
this.h.invoke(this, m, null);
} catch (Throwable able) {
able.getMessage();
}
}
}
6,檢視生成的.class檔案
package com.gupao.designpattern.proxy.self;
import java.lang.reflect.Method;
public class $ProxyO implements SelfProxyInterface {
SelfInvocationHandler h;
public $ProxyO(SelfInvocationHandler var1) {
this.h = var1;
}
public void targetMethod() {
try {
Method var1 = SelfProxyInterface.class.getMethod("targetMethod", new Class[0]);
this.h.invoke(this, var1, (Object[])null);
} catch (Throwable var2) {
var2.getMessage();
}
}
}
7,SelfInvocationHandler接口,定義invoke()方法
public interface SelfInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args);
}
8,SelfJdkProxy,定義newInstance()方法建立代理對象,并實作InvocationHandler接口,重寫invoke()方法,通過反射實作方法最終運作
public class SelfJDKProxy implements SelfInvocationHandler{
private SelfProxyInterface proxyInterface;
public SelfJDKProxy(SelfProxyInterface proxyInterface) {
this.proxyInterface = proxyInterface;
}
public Object instanceProxy() {
System.out.println("代理方法開始...");
SelfProxyInterface instance = (SelfProxyInterface) SelfProxy.newInstance(
new SelfClassLoader(),
proxyInterface.getClass().getInterfaces(), this);
return instance;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
try {
method.invoke(proxyInterface, args);
System.out.println("代理方法結束...");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
9,用戶端執行
public class SelfTest {
public static void main(String[] args) {
SelfJDKProxy proxy = new SelfJDKProxy(new SelfJDKProxyTarget());
SelfProxyInterface proxyInterface = (SelfProxyInterface) proxy.instanceProxy();
System.out.println(proxyInterface);
proxyInterface.targetMethod();
}
}
10,總結
整個手寫動态代理以說明問題為目的,整個流程中所有環境建立都是按照最簡單方式在運作,旨在熟悉整個JDK動态代理的執行流程和底層實作;