โมเดลพร็อกซีเป็นรูปแบบการออกแบบ Java ที่ใช้กันทั่วไป ลักษณะของมันคือคลาสพร็อกซีและคลาสตัวแทนมีอินเทอร์เฟซเดียวกัน คลาสพร็อกซีส่วนใหญ่มีหน้าที่รับผิดชอบในการประมวลผลข้อความล่วงหน้าการกรองข้อความการส่งต่อข้อความไปยังคลาสผู้ได้รับมอบหมายและการประมวลผลข้อความหลังจากเหตุการณ์ มักจะมีความสัมพันธ์ระหว่างคลาสพร็อกซีและคลาสผู้แทน เป้าหมายของคลาสพร็อกซีเกี่ยวข้องกับวัตถุของคลาสตัวแทน วัตถุประสงค์ของคลาสพร็อกซีนั้นไม่ได้ใช้บริการอย่างแท้จริง แต่ให้บริการเฉพาะโดยเรียกใช้วิธีการที่เกี่ยวข้องของวัตถุคลาสตัวแทน
การเปรียบเทียบการใช้งานพร็อกซีแบบไดนามิกที่หลากหลายของ Java
ส่วนต่อประสาน
อินเตอร์เฟส addInterface {int add (int a, int b);} อินเตอร์เฟส subinterface {int sub (int a, int b);} คลาสการดำเนินการ
คลาสเลขคณิตของคลาส AddInterface, Subinterface {@Override สาธารณะ int ย่อย (int a, int b) {return ab; } @Override public int เพิ่ม (int a, int b) {return a+b; -วิธีที่ 1: พร็อกซีแบบไดนามิกที่สร้างขึ้นใน JDK
1. วิธีการใช้งาน
กลไกพร็อกซีแบบไดนามิกที่แนะนำโดย Java หลังจาก JDK1.3 ช่วยให้เราสามารถสร้างคลาสพร็อกซีแบบไดนามิกในระหว่างการรันไทม์ การใช้ AOP โดยใช้พร็อกซีแบบไดนามิกต้องใช้สี่บทบาท: คลาสพร็อกซี, อินเทอร์เฟซคลาสพร็อกซี, อุปกรณ์ทอผ้าและการเรียกร้อง อุปกรณ์ทอผ้าใช้กลไกการสะท้อนส่วนต่อประสานเพื่อสร้างคลาสพร็อกซีจากนั้นสานรหัสลงในคลาสพร็อกซีนี้ พร็อกซีคลาสเป็นเป้าหมายที่กล่าวถึงใน AOP InvocationHandler เป็นส่วนที่มีคำแนะนำและ PointCut
2. การใช้งานอินเตอร์เฟส VinVocationHandler
Class JDKDPQueryHandler ใช้ InvocationHandler {เลขคณิตส่วนตัวของจริง; สาธารณะ jdkdpQueryHandler (arithmetic จริง) {this.real = real; } @Override วัตถุสาธารณะเรียกใช้ (พร็อกซีวัตถุวิธีเมธอด, วัตถุ [] args) โยน throwable {String methodName = method.getName (); System.out.println (วิธีการ); System.out.println ("วิธีการ:" + MethodName + "เริ่มต้นพารามิเตอร์:" + array.aslist (args)); Object result = method.invoke (ของจริง, args); System.out.println ("วิธีการ:"+methodName+"สิ้นสุดผลลัพธ์:"+ผลลัพธ์); ผลการกลับมา; -3. สร้างคลาสพร็อกซีและเรียกคลาสพร็อกซี
คลาสสาธารณะหลัก {ส่วนตัวคงที่ int a = 4, b = 2; วัตถุคงที่สาธารณะ createjdkproxy (arithmetic ของจริง) {วัตถุพร็อกไซม์เมติก = proxy.newproxyinstance (real.getclass (). getclassloader (), real.getClass (). getinterfaces () ส่งมอบ proxyarithmetic; } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {arithmetic real = arithmetic ใหม่ (); Object proxyarithMetic = createjdkproxy (ของจริง); ((addInterface) proxyarithmetic) .Add (a, b); ((subinterface) proxyarithmetic) .sub (a, b); -วิธีที่ 2: การสร้างไบต์แบบไดนามิก (CGLIB)
1. วิธีการใช้งาน
เครื่องเพิ่มประสิทธิภาพและเมธอดิสต์ ตัวเพิ่มประสิทธิภาพสามารถใช้ในการสร้างคลาสแบบไดนามิกซึ่งสามารถสืบทอดคลาสที่ระบุและใช้อินเทอร์เฟซที่ระบุบางอย่าง ในเวลาเดียวกัน Enhancer จำเป็นต้องระบุการโทรกลับก่อนที่จะสร้างคลาส เมื่อมีการเรียกวิธีการคลาสการดำเนินการของวิธีการจะถูกกำหนดให้กับการโทรกลับนี้ MethodInterceptor เป็นอินเทอร์เฟซที่ใช้กันอย่างแพร่หลายมากขึ้นที่สืบทอดมาจากการโทรกลับและมีการประกาศวิธีเดียวเท่านั้น
2. การเปรียบเทียบอินเทอร์เฟซ InvocationHandler (ใน JDK) และ MethodInterceptor อินเตอร์เฟส (ใน CGLIB)
อินเตอร์เฟสสาธารณะ MethodInterceptor ขยายการโทรกลับ {การสกัดกั้นวัตถุสาธารณะ (Object OBJ, Java.lang.reflect.Method, Object [] args, MethodProxy Proxy) โยนได้ } public interface rechocationHandler {วัตถุสาธารณะเรียกใช้ (พร็อกซีวัตถุวิธีวิธีการวัตถุ [] args) โยนได้ - ในแง่ขององค์ประกอบของพารามิเตอร์พารามิเตอร์อินพุตของ MethodInterceptor นั้นมากกว่า 1 InvocationHandler ในความเป็นจริงความหมายของวัตถุพารามิเตอร์สามตัวแรกนั้นเหมือนกับของ InvocationHandler
พารามิเตอร์แรกบ่งชี้ว่าวิธีการโทรมาจากวัตถุใด
พารามิเตอร์ที่สองแสดงถึงวัตถุวิธีการที่เรียกวิธีการ;
พารามิเตอร์ที่สามแสดงรายการพารามิเตอร์อินพุตสำหรับการเรียกนี้
พารามิเตอร์พิเศษเป็นประเภท MethodProxy ซึ่งควรเป็นวัตถุที่สร้างโดย CGLIB เพื่อแทนที่วัตถุวิธี การใช้ MethodProxy จะปรับปรุงประสิทธิภาพมากกว่าการเรียกใช้วิธีการของ JDK ของตัวเองโดยตรง
3. ตระหนัก 1
การใช้งานอินเตอร์เฟส MethodInterceptor
Class CGLIBDPQueryInterceptor ใช้ MethodInterceptor {arithmetic ส่วนตัว Public CGLIBDPQueryInterceptor (arithmetic จริง) {this.real = real; } @Override การสกัดกั้นวัตถุสาธารณะ (เป้าหมายวัตถุวิธีวิธีการวัตถุ [] args, methodProxy proxy) พ่น trowable {String methodName = method.getName (); System.out.println (วิธีการ); System.out.println ("วิธีการ:" + MethodName + "เริ่มต้นพารามิเตอร์:" + array.aslist (args)); // object result = method.invoke (ของจริง, args); // ทั้งสองวิธีสามารถรับผลลัพธ์วัตถุ = proxy.invoke (ของจริง, args); System.out.println ("วิธีการ:"+ methodName+ "สิ้นสุดผลลัพธ์:"+ ผลลัพธ์); ผลการกลับมา; -สร้างคลาสพร็อกซีและเรียกคลาสพร็อกซี
คลาสสาธารณะหลัก {ส่วนตัวคงที่ int a = 4, b = 2; วัตถุสาธารณะคงที่ createCglibproxy (arithmetic จริง) {enhancer enhancer = new enhancer (); enhancer.setCallback (ใหม่ cgLibDPQueryInterceptor (ของจริง)); enhancer.setInterfaces (real.getClass (). getInterfaces ()); return enhancer.create (); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {arithmetic real = arithmetic ใหม่ (); Object proxyarithMetic = createCglibProxy (ของจริง); ((addInterface) proxyarithmetic) .Add (a, b); ((subinterface) proxyarithmetic) .sub (a, b); -โปรดทราบว่า MethodProxy มี 2 วิธีเมื่อดำเนินการฟังก์ชั่น
วัตถุสาธารณะเรียกใช้ (Object OBJ, Object [] args) โยนวัตถุสาธารณะที่สามารถโยนได้เรียกร้อง (Object OBJ, Object [] args)
ในหมู่พวกเขา Javadoc กล่าวว่าวิธีการเรียกใช้ () นี้สามารถใช้สำหรับการดำเนินการของวัตถุอื่น ๆ ในคลาสเดียวกันนั่นคือ OBJ ในวิธีนี้จำเป็นต้องส่งผ่านไปยังวัตถุอื่นของคลาสเดียวกัน หากคุณคิดอย่างรอบคอบคุณจะพบว่าเป้าหมายในการสกัดกั้นวัตถุสาธารณะ (เป้าหมายวัตถุวิธีการวิธีการวัตถุ [] args, methodproxy proxy) เป็นวัตถุพร็อกซีที่ใช้งาน เมื่อวิธีการเพิ่ม () ถูกเรียกผ่านเป้าหมายวิธีการสกัดกั้น () จะถูกเรียกว่าเรียก ถ้า method.invoke (เป้าหมาย, args) ถูกเรียกในวิธีการสกัดกั้น () มันจะเทียบเท่ากับการเรียกวิธีการเพิ่ม () อีกครั้งส่งผลให้วนซ้ำที่ไม่สิ้นสุด แต่ถ้าคุณเรียกใช้เมธอด invoke (ของจริง, args) มันจะไม่เพราะจริงและเป้าหมายเป็นวัตถุที่แตกต่างกันในคลาสเดียวกันจริงเป็นหัวข้อเชิงตรรกะจริงและเป้าหมายเป็นพร็อกซีสำหรับหัวข้อจริง
นี่คือตัวอย่างที่จะจำลอง:
Interface SolveInterface {Void Sollie ();} คลาสการใช้งานจริง lealiNterface {โมฆะสาธารณะแก้ปัญหา () {system.out.println ("แก้ปัญหาจริง!"); }} คลาสเป้าหมายขยาย {วัตถุส่วนตัว obj; โมฆะสาธารณะ setObject (Object obj) {this.obj = obj; } โมฆะส่วนตัว revoke () {ลอง {method method = SoverInterface.class.getMethod ("แก้ปัญหา", คลาสใหม่ [] {}); method.invoke (obj, คลาสใหม่ [] {}); } catch (exception e) {e.printstacktrace (); }} โมฆะสาธารณะแก้ปัญหา () {system.out.println ("การแก้ปัญหาเป้าหมาย!"); เรียก (); - คลาสสาธารณะหลัก {โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น {เป้าหมายเป้าหมาย = new Target (); target.setObject (ใหม่ real ()); // ถูกต้อง // target.setObject (target); // cyclic call เกิดขึ้น target.solve (); -ในความเป็นจริงวิธีการเรียกใช้ () ของวิธีการจะเรียกวิธีการแก้ปัญหาที่สอดคล้องกัน () ตามประเภท OBJ นั่นคือ polymorphism
4. ตระหนัก 2
การใช้งานอินเตอร์เฟส MethodInterceptor
คลาส cglibdpQueryInterceptor ใช้ methodInterceptor {@Override การสกัดกั้นวัตถุสาธารณะ (เป้าหมายวัตถุวิธีการวิธีการวัตถุ [] args, methodProxy proxy) โยน {String methodName = method.getName (); System.out.println (วิธีการ); System.out.println (วิธีการ); System.out.println ("วิธีการ:" + MethodName + "เริ่มต้นพารามิเตอร์:" + array.aslist (args)); // ข้อมูลคลาสพิมพ์: target.getClass (); Omit Object Result = Proxy.invokesuper (เป้าหมาย, args); System.out.println ("วิธีการ:"+methodName+"สิ้นสุดผลลัพธ์:"+ผลลัพธ์); ผลการกลับมา; -สร้างคลาสพร็อกซีและเรียกคลาสพร็อกซี
ชั้นเรียนสาธารณะหลัก {ส่วนตัวคงที่ int a = 4, b = 2; วัตถุคงที่สาธารณะ createCglibproxy () {enhancer enhancer = ใหม่ enhancer (); enhancer.setCallback (ใหม่ cgLibDPQueryInterceptor ()); enhancer.setsuperclass (arithmetic.class); return enhancer.create (); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {arithmetic real = arithmetic ใหม่ (); Object proxyarithMetic = createCglibProxy (); ((addInterface) proxyarithmetic) .Add (a, b); ((subinterface) proxyarithmetic) .sub (a, b); -โปรดทราบว่าตัวเพิ่มประสิทธิภาพไม่ได้ตั้งค่าอินเตอร์เฟสในการใช้งาน 2 เนื่องจาก SuperClass ถูกตั้งค่า (นั่นคือคลาสหลักของคลาสพร็อกซีคือเลขคณิต) คลาสพร็อกซีของเราจะสืบทอดมันและเลขคณิตได้นำอินเทอร์เฟซของเราไปใช้ ในการพิสูจน์สิ่งนี้คุณสามารถพิมพ์ข้อมูลคลาสของ Target.getClass () ในวิธีการสกัดกั้นของ MethodInterceptor คุณจะพบว่าคลาสแม่ของคลาสพร็อกซี CGLIB นั้นแตกต่างกัน ดังนี้:
การดำเนินการ 1:
คลาสสาธารณะ com.test.arithmetic $$ enhancerbycglib $$ 4FA786EB ขยาย java.lang.Object
การดำเนินการ 2:
ชั้นเรียนสาธารณะ com.test.arithmetic $$ enhancerbycglib $$ 4FA786EB ขยาย com.test.arithmetic
วิธีที่ 3: Javassist สร้างพร็อกซีแบบไดนามิก (การสร้างโรงงานตัวแทนหรือการสร้างรหัสแบบไดนามิก)
Javassist เป็นกรอบสำหรับการแก้ไข bytecode ซึ่งช่วยให้คุณสามารถใช้งานไบต์ได้ง่ายๆ มันสามารถกำหนดหรือแก้ไขคลาสระหว่างรันไทม์ หลักการของการใช้ AOP โดยใช้ Javassist คือการปรับเปลี่ยนวิธีการที่จำเป็นต้องป้อนโดยตรงก่อนที่จะโหลด bytecode สิ่งนี้มีประสิทธิภาพมากกว่าการใช้ CGLIB เพื่อใช้ AOP และไม่มีข้อ จำกัด มากมาย หลักการดำเนินการมีดังนี้:
การดำเนินการ 1:
การใช้งานอินเทอร์เฟซ
คลาส JavassistDpQueryHandler ใช้ MethodHandler {@Override วัตถุสาธารณะเรียกใช้ (เป้าหมายวัตถุวิธีการวิธีการพร็อกซีวิธีการวัตถุ [] args) โยน throwable {String methodName = method.getName (); System.out.println (วิธีการ); System.out.println (วิธีการ); System.out.println ("วิธีการ:" + MethodName + "เริ่มต้นพารามิเตอร์:" + array.aslist (args)); Object result = proxy.invoke (เป้าหมาย, args); System.out.println ("วิธีการ:"+methodName+"สิ้นสุดผลลัพธ์:"+ผลลัพธ์); ผลการกลับมา; -สร้างคลาสพร็อกซีและเรียกคลาสพร็อกซี
คลาสสาธารณะหลัก {ส่วนตัวคงที่ int a = 4, b = 2; วัตถุคงที่สาธารณะ createJavAsSistProxy () โยนข้อยกเว้น {ProxyFactory Factory = new ProxyFactory (); Factory.SetSuperClass (arithmetic.class); Factory.Sethandler (ใหม่ JavassistDpQueryHandler ()); Return Factory.CreateClass (). Newinstance (); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น {arithmetic real = new arithmetic (); Object proxyarithMetic = createJavassistProxy (); ((addInterface) proxyarithmetic) .Add (a, b); ((subinterface) proxyarithmetic) .sub (a, b); -หมายเหตุ: คำจำกัดความของวิธีการเรียกใช้ในอินเตอร์เฟส MethodHandler มีดังนี้:
วัตถุสาธารณะเรียกใช้ (เป้าหมายวัตถุวิธีการวิธีการพร็อกซีวิธีการวัตถุ [] args)
วิธีการแสดงถึงวัตถุวิธีการที่เรียกวิธีการพร็อกซีเป็นวัตถุที่สร้างและแทนที่เมธอดโดยคลาสพร็อกซี มิฉะนั้นการใช้ method.invoke (เป้าหมาย, args) จะสร้างการโทรลูปที่ไม่มีที่สิ้นสุด
การดำเนินการ 2:
กระบวนการพร็อกซีทั่วไปของการใช้ Javassist แบบไดนามิกนั้นแตกต่างจากวิธีก่อนหน้าเล็กน้อย ภายใน Javassist รหัส Java แบบไดนามิกสามารถสร้างขึ้นเพื่อสร้าง bytecode พร็อกซีแบบไดนามิกที่สร้างขึ้นด้วยวิธีนี้สามารถยืดหยุ่นได้มากและสามารถสร้างตรรกะทางธุรกิจได้ที่รันไทม์
// custom interceptor interface interceptorhandler { /*** การเรียกใช้วิธีการของวัตถุพร็อกซีแบบไดนามิกจะสะท้อนถึงวิธีนี้ คุณสามารถเพิ่ม AOP-like pre- และ post-operations ในการใช้วิธีนี้ เฉพาะในกรณีที่มีการเพิ่มรหัสต่อไปนี้ลงในวิธีการนี้* วิธีพร็อกซีจะถูกดำเนินการและค่าส่งคืนจะถูกส่งกลับไปยังพร็อกซีและในที่สุดก็กลับไปที่โปรแกรม* @param obj วัตถุวัตถุพร็อกซี* @param เมธอดเมธอด proxy* @param args วัตถุ OBJ, วิธีการ, วัตถุ [] args) โยนได้ } // การใช้งานของ Interceptor Class InterceptorHandlerImpl ดำเนินการ AppleceptorHandler {@Override วัตถุสาธารณะเรียกใช้ (Object OBJ, วิธีการ, วัตถุ [] args) โยน {String methodName = method.getName (); System.out.println (วิธีการ); System.out.println (วิธีการ); System.out.println ("วิธีการ:" + MethodName + "เริ่มต้นพารามิเตอร์:" + array.aslist (args)); Object result = method.invoke (obj, args); System.out.println ("วิธีการ:"+methodName+"สิ้นสุดผลลัพธ์:"+ผลลัพธ์); ผลการกลับมา; }} คลาส myproxyimpl { / ** ชื่อคลาสคำต่อท้ายของคลาสพร็อกซีแบบไดนามิก* / สตริงคงสุดท้ายส่วนตัว proxy_class_name_suffix = "$ myproxy_"; / ** อินเตอร์เฟส interceptor*/ ส่วนตัวสตริงคงสุดท้ายคงที่ interceptor_handler_interface = "com.test.interceptorhandler"; / ** ดัชนีชื่อคลาสของคลาสพร็อกซีแบบไดนามิกเพื่อป้องกันการทำซ้ำของชื่อคลาส*/ private int int proxyclassIndex = 1; /*** อินเทอร์เฟซพร็อกซีแบบไดนามิกที่สัมผัสกับผู้ใช้ส่งคืนวัตถุพร็อกซีแบบไดนามิกของอินเทอร์เฟซที่แน่นอน โปรดทราบว่าการใช้งานพร็อกซีนี้จะต้องใช้กับ com.cuishen.myaop.interceptorhandler interceptor* นั่นคือถ้าผู้ใช้ต้องการใช้พร็อกซีแบบไดนามิกนี้ @Param Classtoproxy String ชื่อคลาสของคลาสการใช้งานของอินเตอร์เฟสที่จะเป็น proxyed แบบไดนามิกเช่น test.studentInfoserviceImpl * @param interceptorHandlerImplClassName ชื่อคลาสของการใช้งาน unglegalAccessException * @throws notfoundexception * @throws ไม่สามารถคอมไพล์เอ็กเซ็ต * @throws classnotfoundexception * @see com.cuishen.myaop.interceptorhandler */ วัตถุสาธารณะคงที่ newproxyinstance NotFoundException, Can'cecompileException, classnotFoundException {class interfaceClass = class.forName (interfaceClassName); คลาส interceptorHandlerImplClass = class.forName (InterceptorHandlerImplClassName); Return DynamicImpleMentsInterface (Classtoproxy, Interfaceclass, InterceptorHandlerImplclass); } /** * การใช้งานแบบไดนามิกของอินเทอร์เฟซที่จะเป็นพร็อกซี * @param classtoproxy สตริงชื่อคลาสของคลาสการใช้งานของอินเตอร์เฟสที่จะเป็น proxyed แบบไดนามิกเช่นการทดสอบ studentinfoserviceimpl * @param interfaceclass คลาสการใช้งานที่ผู้ใช้ให้การใช้งานของอินเทอร์เฟซ interceptor * @return Object ส่งคืนวัตถุพร็อกซีแบบไดนามิกของอินเทอร์เฟซบางอย่าง * @throws NotfoundException * @throws ไม่สามารถคอมไพล์ได้ NotfoundException, ไม่สามารถคอมไพล์เอ็กเซ็ต, InstantiationException, ungleclAccessException {classpool cp = classpool.getDefault (); String interfacename = interfaceclass.getName (); // ระบุชื่อคลาสของพร็อกซีคลาสสตริง proxyclassName = interfacename + proxy_class_name_suffix + proxyclassIndex ++; // ชื่อแพ็คเกจของอินเทอร์เฟซที่จะใช้ + สตริงชื่ออินเตอร์เฟส InterfacenamePath = Interfacename; ctclass ctinterface = cp.getctclass (interfacenamepath); ctclass cc = cp.makeclass (proxyclassName); cc.addinterface (ctinterface); วิธีการ [] methods = interfaceclass.getMethods (); สำหรับ (int i = 0; i <methods.length; i ++) {วิธีการ = วิธีการ [i]; DynamicImplementsMethodsFromInterface (Classtoproxy, CC, วิธีการ, InterceptorHandlerImplclass, i); } return (วัตถุ) cc.toclass (). newInstance (); } /*** เมธอดในการใช้งานแบบไดนามิกของเมธอด* @param classtoproxy สตริงชื่อคลาสของคลาสการใช้งานของอินเทอร์เฟซที่จะเป็นพร็อกซีแบบไดนามิกเช่น test.studentInfoserviceImpl* @param @param emplementer การใช้งานการใช้งาน คลาส InterceptorClass คลาสการใช้งาน Interceptor ที่จัดทำโดยผู้ใช้* @param เมธอดอานด์ดัชนี int ของวิธีการที่จะนำไปใช้* @throws ไม่สามารถคอมไพล์เอ็กเซ็ท*/ โมฆะส่วนตัวแบบคงที่ไดนามิกมิเตอร์เมทิฟฟอเรสต์ (สตริง classtoproxy Generatemethodcode (Classtoproxy, Methodtoimpl, InterceptorClass, MethodIndex); ctmethod cm = ctNewMethod.make (MethodCode, edportiNer); appitiner.addmethod (CM); } /*** รวมตัวกันแบบไดนามิก แน่นอนว่าการใช้วิธีการในพร็อกซีไม่ใช่วิธีการง่ายๆ แต่สะท้อนให้เห็นถึงวิธีการเรียกใช้ในตัวดักและผ่านพารามิเตอร์ที่ได้รับ* @param classtoproxy สตริงชื่อคลาสของคลาสการใช้งานของอินเตอร์เฟส @param คลาส InterceptorClass คลาสการใช้งาน Interceptor ที่ผู้ใช้ให้* @param MethodIndex int ดัชนีของวิธีการที่จะนำไปใช้* @return สตริงสตริงของวิธีการประกอบแบบไดนามิก*/ สตริงคงที่ส่วนตัว generatemethodcode String MethodReturnType = MethodToImpl.getReturnType (). getName (); คลาส [] พารามิเตอร์ = MethodToImpl.getParameterTypes (); คลาส [] sceptionypes = methodtoimpl.getExceptionTypes (); StringBuffer ExceptionBuffer = new StringBuffer (); // การประกาศข้อยกเว้นของวิธีการประกอบถ้า (specantypes.length> 0) ExceptionBuffer.Append ("throws"); สำหรับ (int i = 0; i <sceptionypes.length; i ++) {ถ้า (i! = sceptionypes.length - 1) ExceptionBuffer.Append (specitytypes [i] .getName ()). ภาคผนวก (","); Else ExceptionBuffer.Append (FICTENCETSYPES [i] .getName ()); } stringBuffer parameterBuffer = new StringBuffer (); // รายการพารามิเตอร์ของวิธีการประกอบสำหรับ (int i = 0; i <parameters.length; i ++) {class parameter = พารามิเตอร์ [i]; String parameterType = parameter.getName (); // ไดนามิกระบุชื่อตัวแปรของพารามิเตอร์เมธอด refname = "a" + i; if (i! = parameters.length - 1) ParameterBuffer.Append (ParameterType) .append (" + Refname) .append (", "); ELSE PARAMETERBUFFER.Append (พารามิเตอร์) .Append (" + ชื่อ Refname); } StringBuffer MethodDeclare = new StringBuffer (); // การประกาศวิธีการเนื่องจากเป็นวิธีการที่ใช้อินเทอร์เฟซมันเป็นวิธีการสาธารณะ publicdeclare.append ("สาธารณะ") .append (MethodReturntype) .append ("") .append (MethodName) .append ("("). string interceptorimplName = interceptorclass.getName (); // methodbody methoddeclare.append (interceptor_handler_interface) .append ("interceptor = new") .append (interceptorimplname) .append ("();/n"); // การสะท้อนการโทรของผู้ใช้อินเตอร์เฟส interceptor methodDeclare.Append ("Object returnObj = interceptor.invoke (class.forname (/" " + classtoproxy +"/"). newinstance (), class.forname (/" + classtoproxy + "/") if (parameters.length> 0) MethodDeclare.Append ("วัตถุใหม่ [] {"); MethodDeclare.Append ("($ w) A" + i + ","); else methodDeclare.Append ("null);/n"); // ห่อค่าการส่งคืนของ interceptor การโทรถ้า (methodtoimpl.getReturntype (). isprimitive ()) {ถ้า (methodtoimpl.getreturntype (). เท่ากับ (บูลีน. อื่นถ้า (methodtoimpl.getreturntype (). เท่ากับ (จำนวนเต็ม)) methodDeclare.Append ("return ((จำนวนเต็ม) returnObj) .intValue ();/n"); อื่นถ้า (methodtoimpl.getReturntype (). เท่ากับ (long.type)) methodDeclare.Append ("return ((ยาว) returnObj .longvalue ();/n"); อื่นถ้า (methodtoimpl.getReturntype (). เท่ากับ (float.type)) methodDeclare.Append ("return ((float) returnobj) .floatvalue ();/n"); อื่นถ้า (methodtoimpl.getreturntype (). เท่ากับ (double.type)) methodDeclare.Append ("return (" return ("return (" return ("return (");/n "); อื่น ๆ ถ้า (methodtoimpl.getReturntype () MethodDeclare.Append ("return (" return ("return (" return ("return (" return ();/n "); อื่น ๆ ถ้า (methodtoimpl.getreturntype (). เท่ากับ (double.type)) methodDeclare.Append (" return ("return (" กลับ ( MethodDeclare.Append ("return (" return ("return (" return ("return (" methodtoimpl.getReturntype (). เท่ากับ (double.type)) MethodDeclare.Append ("return (" return ("return (" return ("return ( MethodDeclare.Append ("return (" return ("return (" return ("methodtoimpl.getReturntype (). เท่ากับ ((สอง) returnobj) .doublevalue ();/n"); ((ตัวละคร) returnobj) .charvalue ();/n "); อื่น ๆ ถ้า (methodtoimpl.getReturntype (). เท่ากับ (byte.type)) methodDeclare.Append (" return (byte) returnebj. -bytevalue ();/n "); MethodDeclare.Append ("return ((byte) returnobj) .ByTevalue ();/n"); MethodReturntype + ") returnobj;/n"); คลาส, ชื่อคลาสของคลาสพร็อกซีจำเป็นต้องใช้การใช้งานการสกัดกั้นที่ผู้ใช้กำหนดชื่อคลาสคลาส Object ProxyarithMetic = MyProxyImpl.newProxyInstance ("com.test.arithmeticInterface", "com.test.arithmetic", "com.test.interceptorhand ((arithmeticInterface) proxyarithmetic) .Add (a, b);พิมพ์รหัสสำหรับการใช้อินเทอร์เฟซแบบไดนามิกดังนี้:
Public Int Add (int a0, int a1) {com.test.interceptorhandler interceptor = ใหม่ com.test.interceptorhandlerimpl (); Object returnobj = interceptor.invoke (class.forname ("com.test.arithmetic") newInStance () Object [] {($ w) a0, ($ w) a1}); return ((จำนวนเต็ม) returnobj) .intvalue ();} public int sub (int a0, int a1) {com.test.interceptorhander interceptor.invoke (class.forname ("com.test.arithmetic"). newinstance (), class.forname ("com.test.arithmetic"). getMethods () [1], วัตถุใหม่ [] {($ w) a0, ($ w) a1}); ข้างต้นเป็นการแนะนำรายละเอียดเกี่ยวกับกลไกการใช้งานพร็อกซีแบบไดนามิกใน Java และฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคน