1. การสะท้อนในชวา
1. โหลดแอตทริบิวต์ของคลาสและรหัสอินสแตนซ์ผ่านการสะท้อน:
/*** java.lang.class เป็นแหล่งที่มาของการสะท้อน* เราสร้างคลาสและสร้างไฟล์คลาสที่สอดคล้องกันโดยการรวบรวม (javac.exe) หลังจากเราโหลด (ตัวโหลดคลาสของ JVM) ไฟล์คลาสนี้* หลังจากโหลดไฟล์คลาสนี้ลงในหน่วยความจำมันเป็นคลาสรันไทม์ที่มีพื้นที่แคช คลาสรันไทม์นี้เป็นอินสแตนซ์ของคลาส * คลาสรันไทม์แต่ละคลาสจะโหลดเพียงครั้งเดียว */ คลาส <TudentExam> clazz = studentExam.class; StudentExam StudentExam = clazz.newinstance (); System.err.println (StudentExam); System.out.println (clazz); // ฟิลด์ฟิลด์ = clazz.getfield ("id"); // เรียกแอตทริบิวต์ที่ระบุของคลาสรันไทม์ผ่านแอตทริบิวต์: แอตทริบิวต์คือฟิลด์ฟิลด์ประเภทสาธารณะ = clazz.getDeclaredField ("ID"); // แอตทริบิวต์เป็นฟิลด์ประเภทที่ไม่ใช่แบบสาธารณะ [] ฟิลด์ = clazz.getDeclaredFields (); // รับคุณสมบัติที่ประกาศทั้งหมดของคลาสรันไทม์เอง (คลาสแม่ไม่สามารถทำได้) คลาสหลักใช้ clazz.getfields (); สำหรับ (ฟิลด์ฟิลด์ 2: ฟิลด์) {int i = field2.getModifiers (); ประเภทสตริง = modifier.toString (i); // รับประเภทข้อมูลของแอตทริบิวต์ฟิลด์ System.out.println (ประเภท); } field.setAccessible (จริง); Field.set (StudentExam, 11); System.err.println (StudentExam.getId ()); // เรียกวิธีการที่ระบุของคลาสรันไทม์ผ่านวิธีการสะท้อนกลับวิธี = clazz.getMethod ("setId", integer.class); Method.invoke (StudentExam, 123); // เรียกวิธีการที่ระบุของวิธีการคลาสรันไทม์ [] methods = clazz.getMethods (); // รับวิธีการทั้งหมดที่ประกาศว่าเป็นสาธารณะในคลาสรันไทม์ทั้งหมดและวิธีการคลาสแม่ของพวกเขา [] method2 = clazz.getDeclaredMethods (); // รับวิธีที่ประกาศในคลาสรันไทม์เองสำหรับ (วิธีการ 2: วิธีการ) {system.out.println } // * รับคลาสรันไทม์ของวัตถุผ่านวิธี getClass () ของวัตถุการสอบสอบ = การสอบใหม่ (); Class clazzexam = Exam.getClass ();2. classloader
/** * คำอธิบาย: คลาสโหลดเดอร์, โหลดไฟล์ xx.properties และอ่านข้อมูล * @param * @author xiazhongwei * @data 29 กันยายน 2016: 5:32:56 PM * @return */public void classloader () // พา ธ ถูกเขียนภายใต้แพ็คเกจ: com // able // onlineexam // resources // config.properties inputstream instream = loader.getResourceasstream ("config.properties"); // วิธีการ 2. โหลดไฟล์จาก path ที่ระบุ // fileInputStream fileInputStream = ใหม่ fileInputStream (ไฟล์ใหม่ ("config.properties")); คุณสมบัติคุณสมบัติ = คุณสมบัติใหม่ (); Properties.load (เครื่องมือ); // properties.load (fileInputStream); String prop = properties.getProperty ("โดเมน"); System.out.println (prop); -3. พร็อกซีแบบไดนามิก
พร็อกซีแบบคงที่: ประเภทของคลาสพร็อกซีและวัตถุเป้าหมายจะถูกกำหนดในระหว่างการรวบรวมซึ่งไม่เอื้อต่อการขยายตัวของโปรแกรม ในเวลาเดียวกันคลาสพร็อกซีแต่ละชั้นสามารถให้บริการเพียงหนึ่งอินเตอร์เฟสเท่านั้นดังนั้นพร็อกซีจำนวนมากจะเกิดขึ้นอย่างหลีกเลี่ยงไม่ได้ในการพัฒนาโปรแกรม
พร็อกซีแบบไดนามิก: ไคลเอนต์เรียกวิธีการของวัตถุอื่น ๆ ผ่านคลาสพร็อกซีและสร้างวัตถุพร็อกซีแบบไดนามิกของคลาสเป้าหมายตามที่ต้องการเมื่อโปรแกรมกำลังทำงาน
หลักการของรูปแบบการออกแบบตัวแทน:
ใช้พร็อกซีเพื่อห่อวัตถุแล้วแทนที่วัตถุต้นฉบับด้วยวัตถุพร็อกซีนั้น การโทรไปยังวัตถุต้นฉบับจะต้องผ่านพร็อกซีไม่ว่าเมื่อใดและเมื่อใดที่วัตถุพร็อกซีกำหนดว่าจะเรียกวิธีการอย่างไรและเมื่อใด
แพ็คเกจ com.test.junit; นำเข้า java.lang.reflect.invocationhandler; นำเข้า java.lang.reflect.method; นำเข้า java.lang.reflect.proxy; proxytest ระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {realsubject realsubject = new realsubject (); myinvocationhandler myinvocationhandler = ใหม่ myinvocationhandler (); Object Object = myinvocationhandler.bind (realsubject); หัวเรื่องหัวเรื่อง = (หัวเรื่อง) วัตถุ; subject.action (); }} // การใช้หัวข้ออินเตอร์เฟสพร็อกซีแบบไดนามิก {โมฆะการกระทำ ();} // คลาส realsubject ใช้หัวเรื่อง {@Override การกระทำโมฆะสาธารณะ () {system.out.println ("ฉันเป็นคลาสพร็อกซีอย่าลืมเรียกใช้ฉัน ... "); }} คลาส MyInVocationHandler ใช้การเรียกใช้งาน {Object Object; // การประกาศของวัตถุพร็อกซีของอินเตอร์เฟส/ ** * คำอธิบาย: ①อินสแตนซ์วัตถุพร็อกซี②ส่งคืนวัตถุคลาสพร็อกซี * @param * @author Xiazhongwei * @data 29, 2016: 4:13 this.Object = Object; ส่งคืน proxy.newproxyinstance (Object.getClass (). getClassLoader (), Object.getClass (). getInterfaces (), สิ่งนี้); } / ** * เมื่อมีการเรียกใช้วิธีการที่เขียนใหม่จะเริ่มต้นผ่านวัตถุของคลาสพร็อกซีมันจะถูกแปลงเป็นวิธีการเรียกใช้วิธีการ INRIK ต่อไปนี้ * / @Override วัตถุสาธารณะเรียกใช้ (พร็อกซีวัตถุวิธีวิธีวัตถุ [] args) returnObject; -4. พร็อกซีแบบไดนามิกและ AOP
ตัวอย่างที่ 1
แพ็คเกจ com.atguigu.spring.aop; ส่วนต่อประสานสาธารณะ arithmeticCalculator {int add (int i, int j); int sub (int i, int j); int mul (int i, int j); int div (int i, int j);} แพ็คเกจ com.atguigu.spring.aop; นำเข้า org.springframework.stereotype.component; @component ("arithmeticCalculator") คลาสสาธารณะ arithmeticCalculatorimpl ใช้ arithmeticCalculator {@Override สาธารณะ int เพิ่ม (int i, int j) {int result = i + j; ผลการกลับมา; } @Override Public Int Sub (int i, int j) {int result = i - j; ผลการกลับมา; } @Override สาธารณะ int mul (int i, int j) {int result = i * j; ผลการกลับมา; } @Override สาธารณะ int div (int i, int j) {int result = i / j; ผลการกลับมา; - แพ็คเกจ com.atguigu.spring.aop; คลาสสาธารณะ arithmeticCalculatorLoggingImpl ใช้ arithmeticCalculator {@Override public int เพิ่ม (int i, int j) {system.out.println ("วิธีการเพิ่มเริ่มต้นด้วย [" + i + "," + j + "]"); int result = i + j; System.out.println ("วิธีการเพิ่มจบลงด้วย" + ผลลัพธ์); ผลการกลับมา; } @Override Public Int Sub (int i, int j) {system.out.println ("เมธอดย่อยเริ่มต้นด้วย [" + i + "," + j + "]"); int result = i - j; System.out.println ("Method Sub จะจบลงด้วย" + ผลลัพธ์); ผลการกลับมา; } @Override สาธารณะ int mul (int i, int j) {system.out.println ("วิธีการ mul เริ่มต้นด้วย [" + i + "," + j + "]"); int result = i * j; System.out.println ("วิธีการ mul เริ่มต้นด้วย [" + i + "," + j + "]"); int result = i * j; System.out.println ("วิธีการ MUL จบลงด้วย" + ผลลัพธ์); ผลการกลับมา; } @Override สาธารณะ int div (int i, int j) {system.out.println ("วิธีการ div เริ่มต้นด้วย [" + i + "," + j + "]"); int result = i / j; System.out.println ("Method Div ลงท้ายด้วย" + ผลลัพธ์); ผลการกลับมา; - แพ็คเกจ com.atguigu.spring.aop; นำเข้า java.lang.reflect.invocationhandler; นำเข้า java.lang.reflect.method; นำเข้า java.lang.reflect.proxy; นำเข้า java.util.arrays; ระดับสาธารณะ arithmeticcalculatorloggingproxy {// object เป็นพร็อกซีเอกชน arithmeticCalculator เป้าหมาย; สาธารณะ arithmeticcalculatorloggingproxy (เป้าหมาย arithmeticCalculator) {super (); this.target = เป้าหมาย; } // ส่งคืนพร็อกซีวัตถุสาธารณะ arithmeticCalculator getLoggingProxy () {arithMeticCalculator proxy = null; // ตัวโหลดคลาสใดของวัตถุพร็อกซีรับผิดชอบในการโหลด classloader loader = target.getClass (). getClassLoader (); // ประเภทของวัตถุพร็อกซีนั่นคือมีวิธีการใดบ้าง คลาส [] อินเทอร์เฟซ = คลาสใหม่ [] {arithMeticCalculator.class}; // เมื่อเรียกใช้วิธีการของวัตถุพร็อกซีให้ดำเนินการรหัสต่อไปนี้ InvocationHandler H = new InvocationHandler () { /*** พร็อกซี: วัตถุพร็อกซี โดยทั่วไปวัตถุนี้ไม่ได้ใช้* วิธีการ: วิธีการที่เรียกว่า* args: พารามิเตอร์ที่ส่งผ่านในวิธีการโทร*/ @Override วัตถุสาธารณะเรียกใช้ (พร็อกซีวัตถุวิธีการวิธีการวัตถุ [] args) โยนได้ throwable {// วิธีของวัตถุพร็อกซีจะไม่ถูกเรียกโดยตรงภายในวิธี proxy.toString () จะทำให้ลูปตายเรียกใช้วิธีการเรียกใช้สตริงเมธอด namename = method.getName (); // พิมพ์ log system.out.println ("[ก่อน] วิธีการ" + methodname + "เริ่มต้นด้วย" + array.aslist (args)); // การเรียกผลลัพธ์วัตถุวิธีการเป้าหมาย = null; ลอง {// ผลการแจ้งเตือนล่วงหน้า = method.invoke (เป้าหมาย, args); // การแจ้งเตือนกลับคุณสามารถเข้าถึงค่าส่งคืนของวิธี} catch (nullpointerexception e) {e.printstacktrace (); // การแจ้งเตือนข้อยกเว้นคุณสามารถเข้าถึงข้อยกเว้นของเมธอด} // โพสต์การแจ้งเตือน เนื่องจากวิธีการอาจมีข้อยกเว้นค่าส่งคืนของวิธีการไม่สามารถเข้าถึงได้ // print log system.out.println ("[หลังจาก] วิธีการลงท้ายด้วย" + ผลลัพธ์); ผลการกลับมา; - /*** โหลดเดอร์: ตัวโหลดคลาสที่ใช้โดยวัตถุพร็อกซี * อินเทอร์เฟซ: ระบุประเภทของวัตถุพร็อกซี นั่นคือวิธีการที่สามารถพบได้ในพร็อกซีวัตถุ * H: เมื่อเรียกวิธีการของวัตถุพร็อกซีมันควรตอบสนองอย่างไร? ในความเป็นจริงมันคือการเรียกใช้วิธีการของ InvoCetherHandler*/ proxy = (arithMeticCalculator) proxy.newproxyinstance (โหลดเดอร์อินเตอร์เฟส h); ส่งคืนพร็อกซี; - แพ็คเกจ com.atguigu.spring.aop; นำเข้า org.springframework.context.applicationContext; นำเข้า org.springframework.context.support.classpathxmlapplicationContext; คลาสสาธารณะหลัก {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {// arithmeticCalculator arithmeticCalculator = ใหม่ arithMeticCalculatorImpl (); arithmeticCalculator arithmeticCalculator = ใหม่ arithMeticCalculatorLoggingImpl (); arithMeticCalculator = ใหม่ arithMeticCalculatorLoggingProxy (arithMeticCalculator) .getLoggingProxy (); int result = arithmeticCalculator.add (11, 12); System.out.println ("ผลลัพธ์:" + ผลลัพธ์); ผลลัพธ์ = arithMeticCalculator.div (21, 3); System.out.println ("ผลลัพธ์:" + ผลลัพธ์); -ตัวอย่างที่ 2
แพ็คเกจ com.test.junit; นำเข้า java.lang.reflect.invocationhandler; นำเข้า java.lang.reflect.method; นำเข้า java.lang.reflect.proxy; proxytest ระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {realsubject realsubject = new realsubject (); myinvocationhandler myinvocationhandler = ใหม่ myinvocationhandler (); Object Object = myinvocationhandler.bind (realsubject); หัวเรื่องหัวเรื่อง = (หัวเรื่อง) วัตถุ; subject.action (); }} // การใช้หัวข้ออินเตอร์เฟสพร็อกซีแบบไดนามิก {โมฆะการกระทำ ();} // คลาส realsubject ใช้หัวเรื่อง {@Override การกระทำโมฆะสาธารณะ () {system.out.println ("ฉันเป็นคลาสพร็อกซีอย่าลืมเรียกใช้ฉัน ... "); }} คลาส MyInVocationHandler ใช้การเรียกใช้งาน {Object Object; // การประกาศของวัตถุพร็อกซีของอินเตอร์เฟส/ ** * คำอธิบาย: ①อินสแตนซ์วัตถุพร็อกซี②ส่งคืนวัตถุคลาสพร็อกซี * @param * @author Xiazhongwei * @data 29, 2016: 4:13 this.Object = Object; ส่งคืน proxy.newproxyinstance (Object.getClass (). getClassLoader (), Object.getClass (). getInterfaces (), สิ่งนี้); } / ** * เมื่อมีการเรียกใช้วิธีการที่เขียนใหม่จะเริ่มต้นผ่านวัตถุของคลาสพร็อกซีมันจะถูกแปลงเป็นวิธีการเรียกใช้วิธีการ INRIK ต่อไปนี้ * / @Override วัตถุสาธารณะเรียกใช้ (พร็อกซีวัตถุวิธีวิธีวัตถุ [] args) returnObject; -ขอบคุณสำหรับการอ่านบทความนี้ฉันหวังว่ามันจะช่วยคุณได้ ขอบคุณสำหรับการสนับสนุนเว็บไซต์นี้!