พร็อกซีแบบไดนามิกคือคลาส java.lang.reflect.Proxy ที่สร้างคลาสไบต์แบบไดนามิกตามอินเทอร์เฟซทั้งหมดที่คุณระบุ คลาสนี้จะสืบทอดคลาส Proxy และใช้อินเทอร์เฟซทั้งหมดที่คุณระบุ (อาร์เรย์อินเทอร์เฟซที่คุณส่งผ่านในพารามิเตอร์ ) ; จากนั้นใช้ classloader ที่คุณระบุเพื่อโหลดคลาสไบต์เข้าสู่ระบบและสุดท้ายสร้างอ็อบเจ็กต์ของคลาสดังกล่าวและเริ่มต้นค่าบางส่วนของอ็อบเจ็กต์เช่น invocationHandler ซึ่งเป็นสมาชิกของเมธอดที่สอดคล้องกับอินเทอร์เฟซทั้งหมด . หลังจากการเตรียมใช้งาน วัตถุจะถูกส่งกลับไปยังไคลเอนต์ที่เรียก ด้วยวิธีนี้ สิ่งที่ไคลเอ็นต์ได้รับคือออบเจ็กต์พร็อกซีที่ใช้อินเทอร์เฟซทั้งหมดของคุณ โปรดดูตัวอย่างการวิเคราะห์:
อินเทอร์เฟซสาธารณะ BusinessProcessor {
กระบวนการโมฆะสาธารณะธุรกิจ ();
-
@แทนที่
กระบวนการโมฆะสาธารณะธุรกิจ () {
System.out.println("กำลังประมวลผลธุรกิจ...");
-
-
นำเข้า java.lang.reflect.InvocationHandler;
นำเข้า java.lang.reflect.Method;
-
*หมวดตัวแทนธุรกิจ
* @ผู้เขียนfanhadoop
-
-
BusinessProcessorHandler ระดับสาธารณะใช้ InvocationHandler {
เป้าหมายวัตถุส่วนตัว = null;
BusinessProcessorHandler (เป้าหมายวัตถุ) {
this.target = เป้าหมาย;
-
การเรียกใช้วัตถุสาธารณะ (พร็อกซีวัตถุ, วิธีการวิธีการ, วัตถุ [] args)
ขว้างได้ ขว้างได้ {
ระบบออก
.println("คุณสามารถทำอะไรบางอย่างได้ที่นี่ก่อนดำเนินธุรกิจของคุณ");
ผลลัพธ์ของวัตถุ = method.inurge (เป้าหมาย, args);
ระบบออก
.println("คุณสามารถทำอะไรบางอย่างได้ที่นี่หลังจากดำเนินธุรกิจของคุณแล้ว");
ส่งคืนผลลัพธ์;
-
-
นำเข้า java.lang.reflect.Field;
นำเข้า java.lang.reflect.Method;
นำเข้า java.lang.reflect.Modifier;
นำเข้า java.lang.reflect.Proxy;
การทดสอบชั้นเรียนสาธารณะ {
-
* @param args
-
โมฆะสาธารณะคงหลัก (สตริง [] args) {
BusinessProcessorImpl bpimpl = ใหม่ BusinessProcessorImpl();
ตัวจัดการ BusinessProcessorHandler = BusinessProcessorHandler ใหม่ (bpimpl);
BusinessProcessor bp = (ตัวประมวลผลธุรกิจ) Proxy.newProxyInstance(
bpimpl.getClass().getClassLoader(), bpimpl.getClass()
.getInterfaces() ตัวจัดการ);
bp.กระบวนการธุรกิจ();
System.out.println(bp.getClass().getName());
printClassDefinition(bp.getClass());
-
สาธารณะสตริงคงที่ getModifier (ตัวแก้ไข int) {
ผลลัพธ์สตริง = "";
สวิตช์ (ตัวแก้ไข) {
ตัวแก้ไขกรณีส่วนตัว:
ผลลัพธ์ = "ส่วนตัว";
ตัวแก้ไขกรณีสาธารณะ:
ผลลัพธ์ = "สาธารณะ";
ตัวดัดแปลงเคสป้องกัน:
ผล = "ป้องกัน";
ตัวดัดแปลงเคสบทคัดย่อ:
ผลลัพธ์ = "นามธรรม";
ตัวแก้ไขกรณี FINAL:
ผลลัพธ์ = "สุดท้าย";
ตัวแก้ไขกรณีพื้นเมือง:
ผลลัพธ์ = "พื้นเมือง";
ตัวแก้ไขกรณี STATIC:
ผลลัพธ์ = "คงที่";
ตัวแก้ไขเคสซิงโครไนซ์:
ผลลัพธ์ = "ซิงโครไนซ์";
ตัวแก้ไขกรณี STRICT:
ผลลัพธ์ = "เข้มงวด";
ตัวแก้ไขกรณี TRANSIENT:
ผลลัพธ์ = "ชั่วคราว";
ตัวแก้ไขกรณีระเหย:
ผล = "ระเหย";
ตัวแก้ไขกรณี INTERFACE:
ผลลัพธ์ = "อินเทอร์เฟซ";
-
ส่งคืนผลลัพธ์;
-
โมฆะคงสาธารณะ printClassDefinition (Class clz) {
สตริง clzModifier = getModifier(clz.getModifiers());
ถ้า (clzModifier != null && !clzModifier.equals("")) {
clzModifier = clzModifier + " ";
-
สตริง superClz = clz.getSuperclass().getName();
ถ้า (superClz != null && !superClz.equals("")) {
superClz = "ขยาย" + superClz;
-
อินเทอร์เฟซคลาส [] = clz.getInterfaces ();
สตริงอินเตอร์ = "";
สำหรับ (int i = 0; i < interfaces.length; i++) {
ถ้า (ฉัน == 0) {
inters += "ใช้งาน";
-
อินเตอร์ += อินเทอร์เฟซ [i] .getName ();
-
System.out.println(clzModifier + clz.getName() + " " + superClz + " "
+ อินเตอร์);
System.out.println("{");
ฟิลด์ [] = clz.getDeclaredFields();
สำหรับ (int i = 0; i <fields.length; i++) {
ตัวแก้ไขสตริง = getModifier(fields[i].getModifiers());
ถ้า (ตัวแก้ไข != null && !modifier.equals("")) {
ตัวแก้ไข = ตัวแก้ไข + " ";
-
สตริง fieldName = ฟิลด์ [i] .getName ();
สตริง fieldType = ฟิลด์ [i] .getType().getName();
System.out.println(" " + ตัวแก้ไข + fieldType + " " + fieldName
-
-
System.out.println();
วิธีการ [] วิธีการ = clz.getDeclaredMethods();
สำหรับ (int i = 0; i < method.length; i++) {
วิธีการ วิธีการ = วิธีการ[i];
ตัวแก้ไขสตริง = getModifier(method.getModifiers());
ถ้า (ตัวแก้ไข != null && !modifier.equals("")) {
ตัวแก้ไข = ตัวแก้ไข + " ";
-
สตริง methodName = method.getName();
คลาส returnClz = method.getReturnType();
สตริง retrunType = returnClz.getName();
คลาส [] clzs = method.getParameterTypes();
สตริง paraList = "(";
สำหรับ (int j = 0; j < clzs.length; j ++) {
paraList += clzs[j].getName();
ถ้า (j != clzs.length - 1) {
paraList += `, ";
-
-
paraList += ")";
clzs = method.getExceptionTypes();
ข้อยกเว้นสตริง = "";
สำหรับ (int j = 0; j < clzs.length; j ++) {
ถ้า (เจ == 0) {
ข้อยกเว้น += "พ่น";
-
ข้อยกเว้น += clzs[j].getName();
ถ้า (j != clzs.length - 1) {
ข้อยกเว้น += `, ";
-
-
ข้อยกเว้น += ";";
สตริง methodPrototype = ตัวดัดแปลง + retrunType + " " + methodName
+ paraList + ข้อยกเว้น;
System.out.println(" " + methodPrototype);
-
System.out.println("}");
-
-
บูลีนเท่ากับ (java.lang.Object);
java.lang.String toString();
int hashCode();
กระบวนการธุรกิจเป็นโมฆะ();
-
แน่นอนว่าเมธอด Proxy.newProxyInstance จะทำสิ่งต่อไปนี้:
1. สร้างคลาสแบบไดนามิกตามอินเทอร์เฟซพารามิเตอร์ที่สองที่ส่งผ่านเพื่อใช้อินเทอร์เฟซในอินเทอร์เฟซ ในตัวอย่างนี้ เป็นวิธีการ processBusiness ของอินเทอร์เฟซ BusinessProcessor และสืบทอดคลาส Proxy และเขียนใหม่สามวิธี เช่น hashcode, toString และเท่ากับ สำหรับการใช้งานเฉพาะ โปรดดูที่ ProxyGenerator.generateProxyClass(...); ในตัวอย่างนี้ คลาส $Proxy0 จะถูกสร้างขึ้น
2. โหลดคลาสที่สร้างขึ้นใหม่ลงใน jvm ผ่านพารามิเตอร์แรกที่ส่งผ่านเข้าไป classloder กำลังจะโหลดคลาส $Proxy0
3. ใช้พารามิเตอร์ตัวที่สามเพื่อเรียกตัวสร้าง $Proxy0 (InvocationHandler) ของ $Proxy0 เพื่อสร้างอ็อบเจ็กต์ของ $Proxy0 และใช้พารามิเตอร์อินเทอร์เฟซเพื่อสำรวจวิธีอินเทอร์เฟซทั้งหมด และสร้างอ็อบเจ็กต์ Method เพื่อเริ่มต้นตัวแปรสมาชิก Method ต่างๆ ของ วัตถุ.
4. คืนอินสแตนซ์ของ $Proxy0 ไปยังไคลเอนต์
ตอนนี้สบายดีแล้ว มาดูกันว่าลูกค้าจะปรับอย่างไรแล้วจะชัดเจน
1. ไคลเอนต์ได้รับออบเจ็กต์อินสแตนซ์ของ $Proxy0 เนื่องจาก $Proxy0 สืบทอด BusinessProcessor จึงไม่มีปัญหาในการแปลงเป็น BusinessProcessor
BusinessProcessor bp = (ตัวประมวลผลธุรกิจ)Proxy.newProxyInstance(....);
2. bp.processBusiness();
สิ่งที่เรียกว่าจริงคือ $Proxy0.processBusiness(); ดังนั้นการนำ $Proxy0.processBusiness() ไปใช้งานคือการเรียกเมธอดการเรียกใช้ผ่าน InvocationHandler!