ในบางโปรเจ็กต์ Java MapperScannerConfigurer ใช้ในการรวม mybatis และ spring คลาสนี้จะสร้างคลาสพร็อกซีไดนามิกตามอินเทอร์เฟซโดยอัตโนมัติผ่านพร็อกซีย้อนกลับ
ด้วยเหตุนี้ บทความนี้จึงวิเคราะห์ไดนามิกพร็อกซีของ Java โดยย่อ
บทความนี้ใช้พร็อกซีแบบไดนามิกเพื่อจำลองตัวดักที่จัดการธุรกรรม
อินเตอร์เฟซ:
UserService ส่วนต่อประสานสาธารณะ { public void addUser();ระดับการใช้งาน:
UserServiceImpl ระดับสาธารณะใช้ UserService { addUser เป็นโมฆะสาธารณะ () { System.out.println ("เพิ่มผู้ใช้"); } โมฆะสาธารณะ RemoveUser () { System.out.println ("ลบผู้ใช้"); } public void searchUser () { System.out.println("ค้นหาผู้ใช้");มีสองวิธีในการใช้ Java Dynamic Proxy
1. พร็อกซีแบบไดนามิกที่มาพร้อมกับ jdk
หากต้องการใช้ไดนามิกพร็อกซีที่มาพร้อมกับ jdk คุณต้องเข้าใจอินเทอร์เฟซ InvocationHandler และคลาส Proxy ทั้งคู่อยู่ภายใต้แพ็คเกจ java.lang.reflect
แนะนำ InvocationHandler:
InvocationHandler เป็นอินเทอร์เฟซที่ใช้งานโดยตัวจัดการการร้องขอของอินสแตนซ์พร็อกซี
แต่ละอินสแตนซ์พร็อกซีมี InvocationHandler ที่เกี่ยวข้อง เมื่อเรียกเมธอดบนอินสแตนซ์พร็อกซี เมธอดนี้จะเรียกเมธอดการเรียกใช้ของ InvocationHandler
การแนะนำพร็อกซี:
พร็อกซีจัดเตรียมวิธีการคงที่สำหรับการสร้างคลาสพร็อกซีและอินสแตนซ์แบบไดนามิก
ตัวอย่าง (จำลองการประมวลผลธุรกรรม AOP):
TransactionInterceptor คลาสสาธารณะใช้ InvocationHandler { เป้าหมายวัตถุส่วนตัว; setTarget สาธารณะ (เป้าหมายวัตถุ) { this.target = เป้าหมาย; } @Override วัตถุสาธารณะเรียกใช้ (พร็อกซีวัตถุ วิธีการวิธีการ วัตถุ [] args) พ่น Throwable { System.out.println ("เริ่มต้นธุรกรรม"); method.invoid(target, args); System.out.println("สิ้นสุดธุรกรรม");รหัสทดสอบ:
TestDynamicProxy คลาสสาธารณะ { @Test โมฆะสาธารณะ testJDK() { TransactionInterceptor TransactionInterceptor = ใหม่ TransactionInterceptor(); UserService userService = new UserServiceImpl(); .getClassLoader() userService.getClass().getInterfaces(), ธุรกรรมInterceptor); userServiceProxy.addUser( }}ผลการทดสอบ:
เริ่มธุรกรรมเพิ่มผู้ใช้สิ้นสุดธุรกรรม
แน่นอนว่าเมื่อเราทำการเรียกเมธอดผ่านคลาสพร็อกซี userServiceProxy ธุรกรรมจะถูกเปิดและปิดก่อนและหลังการเรียกเมธอด
2. cglib ไลบรารีบุคคลที่สาม
CGLIB เป็นไลบรารีการสร้างโค้ดที่ทรงพลัง ประสิทธิภาพสูง และมีคุณภาพสูงสำหรับการขยายคลาส Java และการนำอินเทอร์เฟซ Java ไปใช้ในขณะรันไทม์
ความแตกต่างที่ใหญ่ที่สุดระหว่างมันกับพร็อกซีไดนามิกของ JDK คือ:
พร็อกซีไดนามิก JDK ใช้สำหรับอินเทอร์เฟซ ในขณะที่ cglib ใช้พร็อกซีสำหรับคลาส หลักการของ cglib คือการสร้างคลาสย่อยสำหรับคลาสเป้าหมายที่ระบุและเขียนทับวิธีการเพื่อให้ได้การปรับปรุง อย่างไรก็ตาม เนื่องจากมีการใช้การสืบทอด จึงไม่สามารถเป็นคลาสที่แก้ไขได้ พร็อกซี
รหัสตัวอย่างมีดังนี้:
UserServiceCallBack คลาสสาธารณะใช้ MethodInterceptor { @Override การสกัดกั้นวัตถุสาธารณะ (Object o, วิธีการวิธี, Object [] args, MethodProxy methodProxy) พ่น Throwable { System.out.println ("เริ่มต้นธุรกรรมโดย cglib"); ); System.out.println("สิ้นสุดธุรกรรมโดย cglib");รหัสทดสอบ:
TestDynamicProxy คลาสสาธารณะ { @Test โมฆะสาธารณะ testCGLIB() { Enhancer Enhancer = Enhancer ใหม่ (); Enhancer.setSuperclass (UserServiceImpl.class); ; พร็อกซี.addUser(); }}ผลการทดสอบ:
เริ่มธุรกรรมโดยผู้ใช้ cglibadd สิ้นสุดธุรกรรมโดย cglib
ผู้อ่านที่สนใจสามารถทดสอบตัวอย่างในบทความนี้ได้จริง และฉันเชื่อว่าพวกเขาจะได้รับประโยชน์มากมาย