JDK動態代理原理:
- 拿到被代理對象的引用,然後獲取它的接口
- JDK代理重新生成一個類,同時實現我們給的代理對象所實現的接口
- 把被代理對象的引用也拿到了
- 重新動態生成一個class字節碼
- 然後編譯
1. 獲取動態生成的class文件
我們知道了JDK動態代理是動態生成java代碼,然後編譯、加載、執行實現的。我們如何看看JDK自動生成的java文件是怎樣的呢?可以通過以下代碼獲取動態class文件:
byte[] data = ProxyGenerator.generateProxyClass("$Proxy00", new Class[]{Person.class});
FileOutputStream os = new FileOutputStream("$Proxy00.class");
os.write(data);
os.close();
得到 $Proxy00.class 文件
2. 反編譯 $Proxy00.class 文件
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import proxy.jdk.Person;
public final class $Proxy00 extends Proxy implements Person {
private static Method m1;
private static Method m4;
private static Method m3;
private static Method m5;
private static Method m2;
private static Method m0;
public $Proxy00(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 getSex() throws {
try {
return (String)super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String getName() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void findLove() throws {
try {
super.h.invoke(this, m5, (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"));
m4 = Class.forName("proxy.jdk.Person").getMethod("getSex");
m3 = Class.forName("proxy.jdk.Person").getMethod("getName");
m5 = Class.forName("proxy.jdk.Person").getMethod("findLove");
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());
}
}
}
查看發現動態類繼承了 Proxy 實現了代理接口 Person
3. 查看 Proxy 類
Proxy類就是用來創建一個代理對象的類
這個類主要功能:
- 生成源代碼
- 將生成的代碼輸出到磁盤,保存爲.java文件
- 編譯爲.class文件
- 加載.class文件內容到JVM
- 返回被代理對象
去除private方法,把主要參數和方法標識一下,也就是我們需要自己去寫的東西。
package java.lang.reflect;
import ...;
public class Proxy implements java.io.Serializable {
...
/**
* the invocation handler for this proxy instance.
* @serial
*/
// 主要參數,這是一個接口
// 這個參數相當於一個標識
// 這裏運用了一個設計模式
protected InvocationHandler h;
/**
* Prohibits instantiation.
*/
private Proxy() {
}
// 主要構造方法
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces)
throws IllegalArgumentException
{
...
}
// 主要方法
// ClassLoader 也自己實現
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
...
}
public static boolean isProxyClass(Class<?> cl) {
return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
}
public static InvocationHandler getInvocationHandler(Object proxy)
throws IllegalArgumentException
{
...
}
}
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
這個方法的作用就是創建一個代理類對象,它接收三個參數,我們來看下幾個參數的含義:
- loader:一個classloader對象,定義了由哪個classloader對象對生成的代理類進行加載
- interfaces:一個interface對象數組, 表示我們將要給我們的代理對象提供一組什麼樣的接口,如果我們提供了這樣一個接口對象數組,那麼也就是聲明瞭代理類實現了這些接口,代理類就可以調用接口中聲明的所有方法。
- h:一個InvocationHandler對象,表示的是當動態代理對象調用方法的時候會關聯到哪一個InvocationHandler對象上,並最終由其調用。
4. 查看 InvocationHandler 接口
就一個Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
方法
package java.lang.reflect;
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
InvocationHandler類的主要功能:
- InvocationHandler接口是proxy代理實例的調用處理程序實現的一個接口,每一個proxy代理實例都有一個關聯的調用處理程序;在代理實例調用方法時,方法調用被編碼分派到調用處理程序的invoke方法。
5. 自己寫一個 InvocationHandler
無非就該個名字了
GMInvocationHandler.java
package proxy.self;
import java.lang.reflect.Method;
/**
* 代理接口
*
* @author 周廣明
* @version v1 2020/2/16 9:52
*/
public interface GMInvocationHandler {
Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
6. 自己寫一個 ClassLoader
ClassLoader 功能:
- 把類加載到JVM
爲啥要自己寫,因爲自己生成的class文件需要自己指定去加載。
GMClassLoader.java
package proxy.self;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* 重新將class文件動態load到JVM
*
* @author 周廣明
* @version v1 2020/2/16 9:55
*/
public class GMClassLoader extends ClassLoader {
// 類目錄
private File baseDir;
public GMClassLoader() {
this.baseDir = new File("D:\\IdeaProjects\\code\\src\\");
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String className = GMClassLoader.class.getPackage().getName() + "." + name;
if (baseDir != null) {
// 自己生成的類文件
File classFile = new File(baseDir, className.replaceAll("\\.", "/") + ".class");
if (classFile.exists()) {
FileInputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(classFile);
out = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len;
while ((len = in.read(buff)) != -1) {
out.write(buff, 0, len);
}
return defineClass(className, out.toByteArray(), 0, out.size());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
// 刪除臨時文件
classFile.delete();
}
} else {
throw new ClassNotFoundException("未找到類文件");
}
} else {
throw new ClassNotFoundException("類目錄錯誤");
}
return null;
}
}
7. 自己寫一個 Proxy
需要實現上面分析的主要方法
1. 方法 generateSrc(Class<?>[] interfaces):生成源代碼
private static String generateSrc(Class<?>[] interfaces) {
// 換行
String ln = "\r\n";
StringBuilder proxySrc = new StringBuilder();
// 0引入包名
proxySrc.append("package proxy.self;").append(ln);
// 1引入類
proxySrc.append("import proxy.self.GMInvocationHandler;").append(ln);
proxySrc.append("import proxy.self.GMProxy;").append(ln);
proxySrc.append("import java.lang.reflect.Method;").append(ln);
proxySrc.append("import java.lang.reflect.UndeclaredThrowableException;").append(ln);
// 1.1引入代理接口類
for (Class<?> interfaceClass : interfaces) {
proxySrc.append("import ").append(interfaceClass.getName()).append(";").append(ln);
}
// 2類名($GMProxy0)、繼承(自己的Proxy,GMProxy )及實現類,類開始
proxySrc.append("public final class $GMProxy0 extends GMProxy implements ")
// 實現的接口
.append(getInterfacesStr(interfaces)).append(" {");
// ##### 參數 #####
// 3靜態方法參數
// 三個 Object 默認方法
// 3.1hashCode
proxySrc.append("\nprivate static Method m0;").append(ln);
// 3.2equals
proxySrc.append("private static Method m1;").append(ln);
// 3.3toString
proxySrc.append("private static Method m2;").append(ln);
// 3.4獲取實現類的方法
// getMethodsThatImplements(Class<?>[] interfaces) 獲取接口的方法
// getImplementAndMethodsStr(Map<String, Method[]> implementAndMethods) 獲取接口的方法的拼接字符串
proxySrc.append(getImplementAndMethodsStr(getMethodsThatImplements(interfaces))).append(ln);
// ##### 方法 #####
// 4構造方法
proxySrc.append("public $GMProxy0(GMInvocationHandler h) { super(h); }").append(ln);
// 5拷貝hashCode m0
proxySrc.append("public final int hashCode() {\n" +
" try {\n" +
" return (Integer)super.h.invoke(this, m0, null);\n" +
" } catch (RuntimeException | Error var2) {\n" +
" throw var2;\n" +
" } catch (Throwable var3) {\n" +
" throw new UndeclaredThrowableException(var3);\n" +
" }\n" +
" }").append(ln);
// 6拷貝equals m1
proxySrc.append(" public final boolean equals(Object var1) {\n" +
" try {\n" +
" return (Boolean)super.h.invoke(this, m1, new Object[]{var1});\n" +
" } catch (RuntimeException | Error var3) {\n" +
" throw var3;\n" +
" } catch (Throwable var4) {\n" +
" throw new UndeclaredThrowableException(var4);\n" +
" }\n" +
" }").append(ln);
// 7拷貝toString m2
proxySrc.append("public final String toString() {" +
"try {\n" +
" return (String)super.h.invoke(this, m2, null);\n" +
" } catch (RuntimeException | Error var2) {\n" +
" throw var2;\n" +
" } catch (Throwable var3) {\n" +
" throw new UndeclaredThrowableException(var3);\n" +
" }" +
"}").append(ln);
// 8代理接口的方法
// getMethodsImplementStr(Map<String, Method[]> implementAndMethods) 代理方法的實現,字符串
proxySrc.append(getMethodsImplementStr(getMethodsThatImplements(interfaces)));
// 9靜態方法參數賦值
// 前三個注意順序
proxySrc.append("static {\n" +
" try {\n" +
" m0 = Class.forName(\"java.lang.Object\").getMethod(\"hashCode\");\n" +
" m1 = Class.forName(\"java.lang.Object\").getMethod(\"equals\", Class.forName(\"java.lang.Object\"));\n" +
" m2 = Class.forName(\"java.lang.Object\").getMethod(\"toString\");\n")
// getStaticMethodValue(Map<String, Method[]> implementAndMethods) 獲取調用方法,字符串
.append(getStaticMethodValue(getMethodsThatImplements(interfaces)))
.append("} catch (NoSuchMethodException var2) {\n")
.append(" throw new NoSuchMethodError(var2.getMessage());\n")
.append(" } catch (ClassNotFoundException var3) {\n")
.append(" throw new NoClassDefFoundError(var3.getMessage());\n")
.append(" }\n")
.append(" }");
// 類結束
proxySrc.append("}");
return proxySrc.toString();
}
1.1 方法 getInterfacesStr(Class<?>[] interfaces)
拼接實現接口 public final class $Proxy00 extends Proxy implements xxxx {
/**
* 獲取實現接口的字符串
*
* @param interfaces
* @return
*/
private static String getInterfacesStr(Class<?>[] interfaces) {
String ln = ",";
StringBuilder interfaceNames = new StringBuilder();
for (Class<?> interfaceClass : interfaces) {
interfaceNames.append(interfaceClass.getSimpleName()).append(ln);
}
String interfacesStr = interfaceNames.toString();
return interfacesStr.substring(0, interfacesStr.length() - 1);
}
1.2 方法 getMethodsThatImplements(Class<?>[] interfaces)
獲取代理接口中的方法,返回Map,key=接口,value=方法數組
/**
* 獲取接口的方法
*
* @return Map
*/
private static Map<String, Method[]> getMethodsThatImplements(Class<?>[] interfaces) {
Map<String, Method[]> implementAndMethods = new HashMap<>();
for (Class<?> anInterface : interfaces) {
implementAndMethods.put(anInterface.getName(), anInterface.getMethods());
}
return implementAndMethods;
}
1.3 方法 getImplementAndMethodsStr(Map<String, Method[]> implementAndMethods)
獲取接口的方法的靜態方法參數拼接字符串,如:
private static Method m1;
/**
* 獲取接口的方法的拼接字符串
*
* @param implementAndMethods
* @return
*/
private static String getImplementAndMethodsStr(Map<String, Method[]> implementAndMethods) {
StringBuilder interfaceNames = new StringBuilder();
for (String key : implementAndMethods.keySet()) {
Method[] methods = implementAndMethods.get(key);
for (Method method : methods) {
interfaceNames.append("private static Method ").append(method.getName()).append(";").append("\r\n");
}
}
return interfaceNames.toString();
}
1.4 方法 getMethodsImplementStr(Map<String, Method[]> implementAndMethods)
獲取代理方法的實現的字符串,標準如下:
public final [返回類型 方法名() | 方法名(參數...)] throws {
try {
return (返回類型)super.h.invoke(this, m3, [(Object[])null | Object[] 參數]);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
未實現帶參方法
/**
* 代理方法的實現,字符串
*
* @param implementAndMethods
* @return
*/
private static String getMethodsImplementStr(Map<String, Method[]> implementAndMethods) {
StringBuilder methodsImplement = new StringBuilder();
for (String key : implementAndMethods.keySet()) {
Method[] methods = implementAndMethods.get(key);
for (Method method : methods) {
Class<?> returnType = method.getReturnType();
String returnTypeName = returnType.getName();
String methodName = method.getName();
// 判斷 void
if (returnTypeName.equals("void")) {
methodsImplement
.append("public final void ").append(methodName).append("() {\n")
.append(" try {\n")
.append(" super.h.invoke(this, ").append(methodName).append(", null);\n")
.append(" } catch (RuntimeException | Error var2) {\n")
.append(" throw var2;\n")
.append(" } catch (Throwable var3) {\n")
.append(" throw new UndeclaredThrowableException(var3);\n")
.append(" }\n")
.append(" }").append("\r\n");
} else {
methodsImplement
.append("public final ").append(returnTypeName).append(" ").append(methodName).append("() {\n")
.append(" try {\n")
.append(" return (").append(returnTypeName)
.append(")super.h.invoke(this, ")
.append(methodName)
.append(", null);\n")
.append(" } catch (RuntimeException | Error var2) {\n")
.append(" throw var2;\n").append(" } catch (Throwable var3) {\n")
.append(" throw new UndeclaredThrowableException(var3);\n")
.append(" }\n")
.append(" }").append("\r\n");
}
}
}
return methodsImplement.toString();
}
2. 將生成的代碼輸出到磁盤,保存爲.java文件
String path = "D:\\IdeaProjects\\code\\src\\proxy\\self\\";
File f = new File(path + "$GMProxy0.java");
FileWriter fw = new FileWriter(f);
fw.write(proxySrc);
fw.flush();
fw.close();
3. 編譯爲.class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> fileObjects = manager.getJavaFileObjects(f);
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, fileObjects);
task.call();
manager.close();
4. 加載.class文件內容到JVM
// 4加載.class文件內容到JVM
Class<?> proxyClass = loader.findClass("$GMProxy0");
5. 返回被代理對象
// 5返回被代理對象
Constructor<?> c = proxyClass.getConstructor(GMInvocationHandler.class);
return c.newInstance(h);
6. 完整代碼
GMProxy.java
package proxy.self;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* 生成代理對象的代碼
*
* @author 周廣明
* @version v1 2020/2/16 9:54
*/
public class GMProxy {
protected GMInvocationHandler h;
public GMProxy(GMInvocationHandler h) {
this.h = h;
}
public static Object newProxyInstance(
GMClassLoader loader, Class<?>[] interfaces, GMInvocationHandler h) {
try {
// 1生成源代碼
String proxySrc = generateSrc(interfaces);
// 2將生成的代碼輸出到磁盤,保存爲.java文件
String path = "D:\\IdeaProjects\\code\\src\\proxy\\self\\";
File f = new File(path + "$GMProxy0.java");
FileWriter fw = new FileWriter(f);
fw.write(proxySrc);
fw.flush();
fw.close();
// 3編譯爲.class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> fileObjects = manager.getJavaFileObjects(f);
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, fileObjects);
task.call();
manager.close();
// 刪除臨時文件
f.delete();
// 4加載.class文件內容到JVM
Class<?> proxyClass = loader.findClass("$GMProxy0");
// 5返回被代理對象
Constructor<?> c = proxyClass.getConstructor(GMInvocationHandler.class);
return c.newInstance(h);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 生成源代碼
*
* @param interfaces
* @return
*/
private static String generateSrc(Class<?>[] interfaces) {
String ln = "\r\n";
StringBuilder proxySrc = new StringBuilder();
proxySrc.append("package proxy.self;").append(ln);
// 1引入類
proxySrc.append("import proxy.self.GMInvocationHandler;").append(ln);
proxySrc.append("import proxy.self.GMProxy;").append(ln);
proxySrc.append("import java.lang.reflect.Method;").append(ln);
proxySrc.append("import java.lang.reflect.UndeclaredThrowableException;").append(ln);
// 1.2引入代理接口類
for (Class<?> interfaceClass : interfaces) {
proxySrc.append("import ").append(interfaceClass.getName()).append(";").append(ln);
}
// 2類名、繼承及實現類,類開始
proxySrc.append("public final class $GMProxy0 extends GMProxy implements ")
// 實現的接口
.append(getInterfacesStr(interfaces)).append(" {");
// hashCode
proxySrc.append("\nprivate static Method m0;").append(ln);
// equals
proxySrc.append("private static Method m1;").append(ln);
// toString
proxySrc.append("private static Method m2;").append(ln);
// 獲取實現類的方法
proxySrc.append(getImplementAndMethodsStr(getMethodsThatImplements(interfaces))).append(ln);
// 構造方法
proxySrc.append("public $GMProxy0(GMInvocationHandler h) { super(h); }").append(ln);
// hashCode
proxySrc.append("public final int hashCode() {\n" +
" try {\n" +
" return (Integer)super.h.invoke(this, m0, null);\n" +
" } catch (RuntimeException | Error var2) {\n" +
" throw var2;\n" +
" } catch (Throwable var3) {\n" +
" throw new UndeclaredThrowableException(var3);\n" +
" }\n" +
" }").append(ln);
// equals
proxySrc.append(" public final boolean equals(Object var1) {\n" +
" try {\n" +
" return (Boolean)super.h.invoke(this, m1, new Object[]{var1});\n" +
" } catch (RuntimeException | Error var3) {\n" +
" throw var3;\n" +
" } catch (Throwable var4) {\n" +
" throw new UndeclaredThrowableException(var4);\n" +
" }\n" +
" }").append(ln);
// toString
proxySrc.append("public final String toString() {" +
"try {\n" +
" return (String)super.h.invoke(this, m2, null);\n" +
" } catch (RuntimeException | Error var2) {\n" +
" throw var2;\n" +
" } catch (Throwable var3) {\n" +
" throw new UndeclaredThrowableException(var3);\n" +
" }" +
"}").append(ln);
// 代理接口的方法
proxySrc.append(getMethodsImplementStr(getMethodsThatImplements(interfaces)));
// 調用方法
proxySrc.append("static {\n" +
" try {\n" +
" m0 = Class.forName(\"java.lang.Object\").getMethod(\"hashCode\");\n" +
" m1 = Class.forName(\"java.lang.Object\").getMethod(\"equals\", Class.forName(\"java.lang.Object\"));\n" +
" m2 = Class.forName(\"java.lang.Object\").getMethod(\"toString\");\n")
.append(getStaticMethodValue(getMethodsThatImplements(interfaces)))
.append("} catch (NoSuchMethodException var2) {\n")
.append(" throw new NoSuchMethodError(var2.getMessage());\n")
.append(" } catch (ClassNotFoundException var3) {\n")
.append(" throw new NoClassDefFoundError(var3.getMessage());\n")
.append(" }\n")
.append(" }");
// 類結束
proxySrc.append("}");
return proxySrc.toString();
}
/**
* 獲取實現接口的字符串
*
* @param interfaces
* @return
*/
private static String getInterfacesStr(Class<?>[] interfaces) {
String ln = ",";
StringBuilder interfaceNames = new StringBuilder();
for (Class<?> interfaceClass : interfaces) {
interfaceNames.append(interfaceClass.getSimpleName()).append(ln);
}
String interfacesStr = interfaceNames.toString();
return interfacesStr.substring(0, interfacesStr.length() - 1);
}
/**
* 獲取接口的方法
*
* @return Map
*/
private static Map<String, Method[]> getMethodsThatImplements(Class<?>[] interfaces) {
Map<String, Method[]> implementAndMethods = new HashMap<>();
for (Class<?> anInterface : interfaces) {
implementAndMethods.put(anInterface.getName(), anInterface.getMethods());
}
return implementAndMethods;
}
/**
* 獲取接口的方法的拼接字符串
*
* @param implementAndMethods
* @return
*/
private static String getImplementAndMethodsStr(Map<String, Method[]> implementAndMethods) {
StringBuilder interfaceNames = new StringBuilder();
for (String key : implementAndMethods.keySet()) {
Method[] methods = implementAndMethods.get(key);
for (Method method : methods) {
interfaceNames.append("private static Method ").append(method.getName()).append(";").append("\r\n");
}
}
return interfaceNames.toString();
}
/**
* 代理方法的實現,字符串
*
* @param implementAndMethods
* @return
*/
private static String getMethodsImplementStr(Map<String, Method[]> implementAndMethods) {
StringBuilder methodsImplement = new StringBuilder();
for (String key : implementAndMethods.keySet()) {
Method[] methods = implementAndMethods.get(key);
for (Method method : methods) {
Class<?> returnType = method.getReturnType();
String returnTypeName = returnType.getName();
String methodName = method.getName();
if (returnTypeName.equals("void")) {
methodsImplement
.append("public final void ").append(methodName).append("() {\n")
.append(" try {\n")
.append(" super.h.invoke(this, ").append(methodName).append(", null);\n")
.append(" } catch (RuntimeException | Error var2) {\n")
.append(" throw var2;\n")
.append(" } catch (Throwable var3) {\n")
.append(" throw new UndeclaredThrowableException(var3);\n")
.append(" }\n")
.append(" }").append("\r\n");
} else {
methodsImplement
.append("public final ").append(returnTypeName).append(" ").append(methodName).append("() {\n")
.append(" try {\n")
.append(" return (").append(returnTypeName)
.append(")super.h.invoke(this, ")
.append(methodName)
.append(", null);\n")
.append(" } catch (RuntimeException | Error var2) {\n")
.append(" throw var2;\n").append(" } catch (Throwable var3) {\n")
.append(" throw new UndeclaredThrowableException(var3);\n")
.append(" }\n")
.append(" }").append("\r\n");
}
}
}
return methodsImplement.toString();
}
/**
* 獲取調用方法,字符串
*
* @param implementAndMethods
* @return
*/
private static String getStaticMethodValue(Map<String, Method[]> implementAndMethods) {
StringBuilder staticMethodValue = new StringBuilder();
for (String key : implementAndMethods.keySet()) {
Method[] methods = implementAndMethods.get(key);
for (Method method : methods) {
staticMethodValue.append(" ")
.append(method.getName())
.append(" = Class.forName(\"").append(key)
.append("\").getMethod(\"").append(method.getName()).append("\");\n");
}
}
return staticMethodValue.toString();
}
}
8. 再寫一個媒婆類
實現 GMInvocationHandler
GMMatchmaker.java
package proxy.self;
import proxy.jdk.XiaoJuu;
import java.lang.reflect.Method;
/**
* 媒婆
*
* @author 周廣明
* @version v1 2020/2/16 9:57
*/
public class GMMatchmaker implements GMInvocationHandler {
private XiaoJuu target;
public Object getInstance(XiaoJuu target) throws Exception {
this.target = target;
Class<? extends XiaoJuu> targetClass = target.getClass();
System.out.println("被代理者:" + targetClass);
// 獲取並返回代理對象
return GMProxy.newProxyInstance(new GMClassLoader(), targetClass.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String sex = "男".equals(this.target.getSex()) ? "媳婦" : "老公";
System.out.println("----------------");
method.invoke(this.target, args);
System.out.println("----------------");
System.out.println("\n媒婆:你的性別是" + this.target.getSex() + ",需要找" + sex);
System.out.println("\n開始找" + sex + "...");
System.out.println("\n找到小ZZ,覺得闊以,那就辦事");
return null;
}
}
9. 相親者 XiaoJuu
XiaoJuu.java
package proxy.jdk;
/**
* 相親者
*
* @author 周廣明
* @version v1 2020/2/15 14:50
*/
public class XiaoJuu implements Person {
private String name = "小Juu";
private String sex = "女";
@Override
public String getName(String aa, int bb) {
return name;
}
@Override
public String getSex() {
return sex;
}
@Override
public void findLove() {
System.out.println("姓名:" + name + ",性別:" + sex);
System.out.println("找對象要求:");
System.out.println("高富帥");
System.out.println("有車有房");
System.out.println("身高180cm,體重70kg");
}
}
10. 安排相親
TestWoo.java
package proxy.jdk;
import proxy.self.GMMatchmaker;
import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
/**
* @author 周廣明
* @version v1 2020/2/15 14:58
*/
public class TestWoo {
public static void main(String[] args) {
// 要相親者
XiaoJuu xiaoJuu = new XiaoJuu();
// 媒婆出場
GMMatchmaker meiPo = new GMMatchmaker();
// 代理對象
try {
Person obj = (Person) meiPo.getInstance(xiaoJuu);
System.out.println("代理人:" + obj.getClass() + "\n");
obj.findLove();
} catch (Exception e) {
e.printStackTrace();
}
}
}
11. 相親結果
被代理者:class proxy.jdk.XiaoJuu
代理人:class proxy.self.$GMProxy0
----------------
姓名:小Juu,性別:女
找對象要求:
高富帥
有車有房
身高180cm,體重70kg
----------------
媒婆:你的性別是女,需要找老公
開始找老公...
找到小ZZ,覺得闊以,那就辦事
Process finished with exit code 0