1. โหมดตัวแทน
โมเดลพร็อกซีเรียกว่าพร็อกซีหรือตัวแทนเป็นภาษาอังกฤษและทั้งคู่สามารถแปลเป็น "ตัวแทน" เป็นภาษาจีนได้ พร็อกซีที่เรียกว่าบุคคลหนึ่งหรือสถาบันหนึ่งดำเนินการในนามของบุคคลอื่นหรือสถาบันอื่น ในบางกรณีลูกค้าไม่ต้องการหรือไม่สามารถอ้างถึงวัตถุโดยตรงและวัตถุพร็อกซีสามารถทำหน้าที่เป็นตัวกลางระหว่างลูกค้าและวัตถุเป้าหมาย
อธิบายความแตกต่างระหว่างตัวแทนต่าง ๆ โดยเพียงแค่จำลองกระบวนการดำเนินการของการทำธุรกรรม
1.1 พร็อกซีคงที่
ซอร์สโค้ดถูกสร้างขึ้นโดยโปรแกรมเมอร์หรือสร้างโดยอัตโนมัติโดยเครื่องมือเฉพาะจากนั้นรวบรวม ก่อนที่โปรแกรมจะทำงานไฟล์. class ของคลาสพร็อกซีจะมีอยู่แล้ว
ส่วนต่อประสานสาธารณะ persondao {void saveperson ();} Persondaoimpl คลาสสาธารณะใช้ persondao {@Override โมฆะสาธารณะ saveperson () {system.out.println ("บันทึกบุคคล"); - การทำธุรกรรมระดับสาธารณะ {void เริ่มต้น () {system.out.println ("เริ่มการทำธุรกรรม"); } void commit () {system.out.println ("commit"); -ถัดไปเขียนคลาสพร็อกซีแบบคงที่ --- ใช้อินเทอร์เฟซ Persondao
/*** คลาสพร็อกซีแบบคงที่* @author qjc*/คลาสสาธารณะ persondaoproxy ใช้ persondao {persondao persondao; ธุรกรรมการทำธุรกรรม สาธารณะ Persondaoproxy (Persondao Persondao, ธุรกรรมการทำธุรกรรม) {this.persondao = persondao; this.transaction = ธุรกรรม; } @Override โมฆะสาธารณะ saveperson () {this.transaction.beginTransaction (); this.persondao.saveperson (); this.transaction.Commit (); -ทดสอบ
/*** ทดสอบพร็อกซีแบบคงที่* @author qjc*/คลาสสาธารณะ testpersonproxy {@test โมฆะสาธารณะ testsave () {persondao persondao = persondaoimpl ใหม่ (); ธุรกรรมธุรกรรม = ธุรกรรมใหม่ (); persondaoproxy proxy = persondaoproxy ใหม่ (Persondao, ธุรกรรม); Proxy.saveperson (); -สรุป:
1. โหมดพร็อกซีแบบคงที่ไม่ได้นำการทำธุรกรรมกลับมาใช้ซ้ำ
2. สมมติว่ามี 100 คลาสและ 100 พร็อกซี ในอินเทอร์เฟซมีกี่วิธีจะต้องใช้วิธีการกี่วิธีในเลเยอร์พร็อกซีและจำนวนธุรกรรมที่ต้องเปิดและส่งเป็นวิธีการหลายวิธี
3. หากพร็อกซีใช้หลายอินเทอร์เฟซถ้าหนึ่งในอินเทอร์เฟซเปลี่ยนแปลง (เพิ่มวิธีการ) พร็อกซีจะต้องเปลี่ยนตาม
1.2 JDK Dynamic Proxy
คลาสพร็อกซีแบบไดนามิก: มันถูกสร้างขึ้นแบบไดนามิกโดยใช้กลไกการสะท้อนเมื่อโปรแกรมทำงาน
พร็อกซีแบบไดนามิกของ JDK จะต้องเป็นไปตามเงื่อนไขสี่ประการ: 1. อินเทอร์เฟซเป้าหมาย 2. คลาสเป้าหมาย 3. interceptor 4. คลาสพร็อกซี
การใช้อินเทอร์เฟซ Persondao คลาส Persondaoimpl และคลาสธุรกรรมในตัวอย่างก่อนหน้า
เขียน Interceptor
นำเข้า java.lang.reflect.invocationhandler; นำเข้า java.lang.reflect.method;/** * interceptor * 1. นำเข้าคลาสเป้าหมายใน * 2 นำเข้าสิ่งต่าง ๆ ใน * 3. การเรียกใช้การทำธุรกรรมเริ่มต้น // การทำธุรกรรมการทำธุรกรรมส่วนตัวคลาส สกัดกั้นสาธารณะ (เป้าหมายวัตถุ, ธุรกรรมการทำธุรกรรม) {this.target = เป้าหมาย; this.transaction = ธุรกรรม; } / *** @param พร็อกซีอินสแตนซ์ของคลาสพร็อกซีของวัตถุเป้าหมาย* @param เมธอดที่สอดคล้องกับอินสแตนซ์เมธอดที่เรียกวิธีการอินเตอร์เฟสบนอินสแตนซ์พร็อกซี* @param args อาร์เรย์วัตถุที่ส่งไปยังค่าพารามิเตอร์เมธอด throwable {string methodName = method.getName (); if ("SavePerson" .Equals (MethodName) || "DeletePerson" .Equals (MethodName) || "UpdatePerson" .Equals (MethodName)) {this.transaction.beginTransaction (); // เปิดใช้งานวิธีการทำธุรกรรม invoke (เป้าหมาย); // เรียกวิธีการเป้าหมาย this.transaction.Commit (); // ส่งธุรกรรม} else {method.invoke (เป้าหมาย); } return null; -ทดสอบ
/*** ทดสอบ JDK Dynamic Proxy* @author qjc*/คลาสสาธารณะ testjdkproxy {@test โมฆะสาธารณะทดสอบ () {/*** 1. สร้างวัตถุเป้าหมาย* 2. สร้างธุรกรรม* 3 สร้าง interceptor* 4 ธุรกรรมธุรกรรม = ธุรกรรมใหม่ (); interceptor interceptor = interceptor ใหม่ (เป้าหมาย, ธุรกรรม); /*** พารามิเตอร์ 1: ตั้งค่าคลาสโหลดเดอร์ที่ใช้โดยรหัสซึ่งโดยทั่วไปใช้ตัวโหลดคลาสเดียวกันกับคลาสเป้าหมาย* พารามิเตอร์ 2: ตั้งค่าอินเตอร์เฟสที่ใช้โดยคลาสพร็อกซีและใช้อินเทอร์เฟซเดียวกันกับคลาสเป้าหมาย* พารามิเตอร์ 3: ตั้งค่าการเรียกกลับ เมื่อวิธีการของวัตถุพร็อกซีถูกเรียกใช้วิธีการเรียกใช้ของวัตถุที่ระบุจะถูกเรียกว่า*/ persondao persondao = (persondao) พร็อกซี NewProxyInstance (target.getClass (). getClassloader (), target.getClass () Persondao.saveperson (); -สรุป :
1. เนื่องจากคลาสพร็อกซีที่สร้างโดย JDKProxy ใช้อินเทอร์เฟซวิธีทั้งหมดในคลาสเป้าหมายจึงรวมอยู่ในคลาสพร็อกซี
2. วิธีการทั้งหมดของคลาสพร็อกซีที่สร้างขึ้นจะสกัดกั้นวิธีการทั้งหมดของคลาสเป้าหมาย เนื้อหาของวิธีการเรียกใช้ในตัวดักเป็นองค์ประกอบของแต่ละวิธีของคลาสพร็อกซี
3. อินเทอร์เฟซจะต้องมีอยู่เมื่อใช้ JDKProxy
4. พารามิเตอร์สามตัวในวิธีการเรียกใช้สามารถเข้าถึง API ของวิธีที่เรียกว่าพารามิเตอร์ของวิธีที่เรียกว่าและประเภทการส่งคืนของวิธีการที่เรียกว่าของคลาสเป้าหมาย
ข้อบกพร่อง:
1. ใน interceptor ยกเว้นการเรียกใช้วิธีเป้าหมายของวัตถุเป้าหมายฟังก์ชั่นค่อนข้างเดี่ยว ในตัวอย่างนี้สามารถประมวลผลธุรกรรมได้เท่านั้น
2. คำพิพากษาหากคำพิพากษาของวิธีการเรียกใช้ใน interceptor นั้นไม่น่าเชื่อถือในสภาพแวดล้อมการพัฒนาที่แท้จริงเพราะเมื่อมีคำสั่งมากมายหากมีการเขียนข้อความ
1.3 CGLIB DYNAMIC PROXY
ใช้คลาส Persondaoimpl และคลาสธุรกรรมในตัวอย่างก่อนหน้า (ไม่มีอินเทอร์เฟซ)
เขียนคลาส Interceptor
นำเข้า net.sf.cglib.proxy.enhancer; นำเข้า net.sf.cglib.proxy.methodinterceptor; นำเข้า net.sf.cglib.proxy.methodproxy;/*** cglib proxy interceptor* @author qjc*/ // การทำธุรกรรมการทำธุรกรรมส่วนตัวระดับส่วนตัว สกัดกั้นสาธารณะ (เป้าหมายวัตถุ, ธุรกรรมการทำธุรกรรม) {this.target = เป้าหมาย; this.transaction = ธุรกรรม; } / ** * สร้างวัตถุพร็อกซีของวัตถุเป้าหมาย * * @return * / วัตถุสาธารณะ createProxy () {// // การเพิ่มประสิทธิภาพการเพิ่มประสิทธิภาพของรหัส = ใหม่ enhancer (); // คลาสนี้ใช้เพื่อสร้างพร็อกซีวัตถุเพิ่มประสิทธิภาพ SetCallback (นี้); // พารามิเตอร์คือ Interceptor Enhancer.setSuperClass (target.getClass ()); // ตั้งค่าการเพิ่มระดับการส่งคืนคลาสแม่ // สร้างวัตถุพร็อกซี}/ *** @param OBJ อินสแตนซ์ของวัตถุเป้าหมายพร็อกซีคลาส* @param เมธอดเมธอดอินสแตนซ์ที่เรียกเมธอดพาเรนต์คลาสบนอินสแตนซ์พร็อกซี* @param args อาร์เรย์ของวัตถุที่ส่งไปยังค่าพารามิเตอร์เมธอด Object [] args, methodproxy methodproxy) พ่น {this.transaction.begintransaction (); method.invoke (เป้าหมาย); this.transaction.Commit (); คืนค่า null; -ทดสอบ
/*** ทดสอบ cglib พร็อกซีแบบไดนามิก* วัตถุพร็อกซีที่สร้างขึ้นผ่าน cglib คลาสพร็อกซีเป็นคลาสย่อยของคลาสเป้าหมาย* @author qjc*/คลาสสาธารณะ testcglibproxy {@test public public void testsave () {object เป้าหมาย = ใหม่ persondaoimpl (); ธุรกรรมธุรกรรม = ธุรกรรมใหม่ (); interceptor interceptor = interceptor ใหม่ (เป้าหมาย, ธุรกรรม); persondaoimpl persondaoimpl = (persondaoimpl) interceptor.createproxy (); Persondaoimpl.saveperson (); -สรุป:
1. CGLIB เป็นไลบรารีคลาสการสร้างรหัสคุณภาพสูงและมีประสิทธิภาพสูง มันสามารถขยายคลาส Java และใช้อินเตอร์เฟส Java ในระหว่างการรันไทม์
2. ใช้ CGLIB เพื่อสร้างคลาสพร็อกซีเป็นคลาสย่อยของคลาสเป้าหมาย
3. ไม่จำเป็นต้องใช้อินเทอร์เฟซในการสร้างคลาสพร็อกซีโดยใช้ cglib
4. คลาสพร็อกซีที่สร้างขึ้นโดย CGLIB แทนที่วิธีการของคลาสแม่
5. เนื้อหาของวิธีการสกัดกั้นในการสกัดกั้นคือ ความแตกต่างระหว่างวิธีการ CGLIB และพร็อกซีไดนามิก JDK ในคลาสพร็อกซี:
JDK:
คลาสเป้าหมายและคลาสพร็อกซีใช้อินเทอร์เฟซทั่วไป
Interceptor จะต้องใช้อินเทอร์เฟซ InvocationHandler และเนื้อหาของ Body Method Method ในอินเทอร์เฟซนี้เป็นเนื้อหาของตัวถังวิธีพร็อกซี
cglib:
คลาสเป้าหมายคือคลาสแม่ของคลาสพร็อกซี
Interceptor จะต้องใช้อินเทอร์เฟซ MethodInterceptor และวิธีการสกัดกั้นในอินเตอร์เฟสคือวิธีการของคลาสพร็อกซีและกลไกการเพิ่มประสิทธิภาพของ bytecode ใช้เพื่อสร้างวัตถุพร็อกซี
2. การเขียนโปรแกรมเชิงเส้นที่มุ่งเน้น
OOP (การเขียนโปรแกรมเชิงวัตถุ): encapsulation, การสืบทอด, polymorphism, abstraction
การห่อหุ้มการจัดการรหัสขั้นพื้นฐานและแบบแยกส่วน แต่ละคลาสอาจมีฟังก์ชั่นของตัวเอง หากมีอะไรผิดพลาดเพียงแค่มองหาใครสักคนที่จะพูดคุยเรื่องนี้ จากมุมมองของการดัดแปลงอาจมีความเสี่ยงในการปรับเปลี่ยนรหัสโดยตรง นี่ไม่ใช่ทางออกระยะยาว สิ่งที่เป็นธรรมชาติที่สุดคือการเปลี่ยนจากการห่อหุ้มประเภท อย่างไรก็ตามวิธีการรวมประเภทใหม่และระบบเก่าดังนั้นจึงจำเป็นต้องสร้างความสัมพันธ์ระหว่างเลือดระหว่างชั้นเรียน จากนั้นนี่คือข้อกำหนดของการสืบทอด ผ่านการสืบทอดคุณจะพบว่าชั้นเรียนเหล่านี้เกี่ยวข้องกันและมีความสัมพันธ์ระหว่างพ่อ-ลูกระหว่างพวกเขา จากนั้นบนพื้นฐานของการสืบทอด polymorphisms มีลักษณะเด็ดขาด ดังนั้นโดยทั่วไปแล้วเชื่อว่าคุณลักษณะหลักที่สุดของวัตถุที่มุ่งเน้นเป็นความหลากหลายจริง ๆ ไม่กี่คนแรกที่วางรากฐาน Polymorphism เป็นคุณสมบัติหลัก วิธีการเขียนใหม่ในคลาสย่อยแสดงถึงการขยายของระดับนี้และสามารถรวมเข้ากับระบบเก่าและสามารถทำงานได้ตามปกติ นี่คือการใช้ซ้ำของระดับนี้วิธีการใหม่ระบบเก่าส่วนขยายและการใช้ซ้ำ
AOP (การเขียนโปรแกรมที่เน้นส่วน):
การเขียนโปรแกรมที่จำเป็นเป็นเทคโนโลยีที่เพิ่มฟังก์ชั่นให้กับโปรแกรมแบบไดนามิกโดยไม่ต้องแก้ไขซอร์สโค้ดผ่านพร็อกซีแบบไดนามิกแบบรันไทม์
ความแตกต่างระหว่าง OOP และ AOP:
OOP: การห่อหุ้มนามธรรมดำเนินการในหน่วยงานและคุณสมบัติและพฤติกรรมของกระบวนการประมวลผลธุรกิจเพื่อให้ได้การแบ่งที่ชัดเจนยิ่งขึ้นของหน่วยตรรกะ
AOP: แยกตรรกะการตัดข้ามในกระบวนการธุรกิจ มันเผชิญกับขั้นตอนหรือขั้นตอนที่แน่นอนในกระบวนการเพื่อให้ได้ผลการแยกการเชื่อมต่อต่ำระหว่างส่วนของกระบวนการลอจิก แนวคิดการออกแบบทั้งสองนี้มีความแตกต่างที่สำคัญในเป้าหมาย AOP ประสบความสำเร็จในการใช้บล็อกรหัสใหม่
กลไกพร็อกซีของ AOP ในฤดูใบไม้ผลิ:
1. หากวัตถุเป้าหมายใช้หลายอินเทอร์เฟซสปริงใช้ Java.lang.lang.reflect.proxy Class Proxy
ข้อดี: เนื่องจากมีอินเทอร์เฟซระบบจึงเข้ากันอย่างหลวม
ข้อเสีย: สร้างอินเทอร์เฟซสำหรับแต่ละคลาสเป้าหมาย
2. หากวัตถุเป้าหมายไม่ได้ใช้อินเทอร์เฟซใด ๆ สปริงจะใช้ไลบรารี CGLIB เพื่อสร้างคลาสย่อยของวัตถุเป้าหมาย
ข้อดี: เนื่องจากคลาสพร็อกซีและคลาสเป้าหมายได้รับการสืบทอดจึงไม่จำเป็นต้องมีอินเทอร์เฟซอยู่
ข้อเสีย: เนื่องจากไม่มีการใช้อินเทอร์เฟซการมีเพศสัมพันธ์ของระบบจึงไม่ดีเท่าพร็อกซีแบบไดนามิกโดยใช้ JDK
การใช้อินเทอร์เฟซ Persondao, คลาส Persondaoimpl และคลาสธุรกรรม
เขียนการกำหนดค่าสปริง
<bean id = "persondao"> </epean> <bean id = "ธุรกรรม"> </epean> <aop: config> <!-การแสดงออกของ Pointcut กำหนดคลาสเป้าหมาย-> <aop: pointcut expression = "การดำเนินการ (cn.qjc.aop.aop.xml.persondaoimpl.* ref = "การทำธุรกรรม"> <aop: ก่อนวิธี = "artialtransaction" pointcut-ref = "perform"/> <aop: method-returning method = "commit" pointcut-ref = "ดำเนินการ"/> </aop: แง่มุม> </aop: config>
ทดสอบ
/*** ทดสอบสปริงแบบไดนามิกพร็อกซี* @author qjc*/คลาสสาธารณะ transactionTest {@Test โมฆะสาธารณะ testSave () {applicationContext context = ใหม่ classPathxMlApplicationContext ("CN/QJC/AOP/XML/ApplicationContext.xml"); persondao persondao = (persondao) บริบท getBean ("persondao"); Persondao.saveperson (); -ฤดูใบไม้ผลิหลักการของ AOP
1. เมื่อคอนเทนเนอร์สปริงเริ่มต้นแล้วถั่วสองตัวจะถูกโหลดและอินสแตนซ์
2. เมื่อคอนเทนเนอร์สปริงแยกวิเคราะห์ไฟล์การกำหนดค่าเป็น <AOP: config>, แยกวิเคราะห์นิพจน์จุดตัดและจับคู่ถั่วของเนื้อหาคอนเทนเนอร์สปริงตามนิพจน์ที่ตัดจุด
3. หากการแข่งขันสำเร็จให้สร้างวัตถุพร็อกซีสำหรับถั่ว
4. เมื่อลูกค้าใช้บริบท GetBean เพื่อรับวัตถุหากวัตถุมีวัตถุพร็อกซีมันจะส่งคืนวัตถุพร็อกซี หากไม่มีวัตถุพร็อกซีมันจะส่งคืนวัตถุเอง
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น