portaldacalheta.pt
  • หลัก
  • การเพิ่มขึ้นของระยะไกล
  • ผู้คนและทีมงาน
  • การวางแผนและการพยากรณ์
  • การออกแบบ Ux
ส่วนหน้าของเว็บ

การสอนคลาส Java ขั้นสูง: คำแนะนำในการโหลดคลาสซ้ำ



ใน โครงการพัฒนา Java เวิร์กโฟลว์ทั่วไปเกี่ยวข้องกับการรีสตาร์ทเซิร์ฟเวอร์พร้อมกับการเปลี่ยนคลาสทุกครั้งและไม่มีใครบ่นเกี่ยวกับเรื่องนี้ นั่นคือข้อเท็จจริงเกี่ยวกับการพัฒนา Java เราทำงานแบบนั้นมาตั้งแต่วันแรกกับ Java แต่การรีโหลดคลาส Java นั้นยากที่จะบรรลุหรือไม่? และปัญหานั้นทั้งท้าทายและน่าตื่นเต้นในการแก้ไขหรือไม่ นักพัฒนา Java ที่มีทักษะ เหรอ? ในบทช่วยสอนคลาส Java นี้ฉันจะพยายามแก้ไขปัญหาช่วยให้คุณได้รับประโยชน์ทั้งหมดจากการโหลดคลาสแบบ on-the-fly และเพิ่มประสิทธิภาพการทำงานของคุณอย่างมหาศาล

มักไม่ค่อยมีการพูดถึงการรีโหลดคลาส Java และมีเอกสารประกอบการสำรวจกระบวนการนี้น้อยมาก ฉันมาที่นี่เพื่อเปลี่ยนแปลงสิ่งนั้น บทช่วยสอนคลาส Java นี้จะให้คำอธิบายทีละขั้นตอนเกี่ยวกับกระบวนการนี้และช่วยให้คุณเชี่ยวชาญเทคนิคที่น่าทึ่งนี้ โปรดทราบว่าการนำการโหลดคลาส Java มาใช้นั้นต้องใช้ความระมัดระวังเป็นอย่างมาก แต่การเรียนรู้วิธีการทำจะทำให้คุณอยู่ในลีกใหญ่ทั้งในฐานะนักพัฒนา Java และในฐานะสถาปนิกซอฟต์แวร์ นอกจากนี้ยังจะไม่เจ็บที่จะเข้าใจ วิธีหลีกเลี่ยงข้อผิดพลาด Java 10 ข้อที่พบบ่อยที่สุด .



การตั้งค่าพื้นที่ทำงาน

ซอร์สโค้ดทั้งหมดสำหรับบทช่วยสอนนี้อัปโหลดบน GitHub ที่นี่ .



ในการรันโค้ดในขณะที่คุณทำตามบทช่วยสอนนี้คุณจะต้อง Maven , ไป และอย่างใดอย่างหนึ่ง คราส หรือ IntelliJ IDEA .



หากคุณกำลังใช้ Eclipse:

  • เรียกใช้คำสั่ง mvn eclipse:eclipse เพื่อสร้างไฟล์โครงการของ Eclipse
  • โหลดโครงการที่สร้างขึ้น
  • กำหนดเส้นทางเอาต์พุตเป็น target/classes

หากคุณใช้ IntelliJ:

  • นำเข้า pom ของโปรเจ็กต์ ไฟล์.
  • IntelliJ จะไม่คอมไพล์อัตโนมัติเมื่อคุณเรียกใช้ตัวอย่างใด ๆ ดังนั้นคุณต้อง:
  • เรียกใช้ตัวอย่างภายใน IntelliJ จากนั้นทุกครั้งที่คุณต้องการรวบรวมคุณจะต้องกด Alt+B E
  • เรียกใช้ตัวอย่างภายนอก IntelliJ ด้วย run_example*.bat ตั้งค่าคอมไพเลอร์อัตโนมัติของ IntelliJ เป็น true จากนั้นทุกครั้งที่คุณเปลี่ยนไฟล์ java ใด ๆ IntelliJ จะคอมไพล์โดยอัตโนมัติ

ตัวอย่างที่ 1: การโหลดคลาสใหม่ด้วย Java Class Loader

ตัวอย่างแรกจะทำให้คุณเข้าใจทั่วไปเกี่ยวกับตัวโหลดคลาส Java นี่คือซอร์สโค้ด

รับสิ่งต่อไปนี้ User นิยามคลาส:



public static class User { public static int age = 10; }

เราสามารถทำสิ่งต่อไปนี้:

public static void main(String[] args) { Class userClass1 = User.class; Class userClass2 = new DynamicClassLoader('target/classes') .load('qj.blog.classreloading.example1.StaticInt$User'); ...

ในตัวอย่างบทช่วยสอนนี้จะมีสอง User คลาสที่โหลดลงในหน่วยความจำ userClass1 จะถูกโหลดโดยตัวโหลดคลาสเริ่มต้นของ JVM และ userClass2 โดยใช้ DynamicClassLoader ซึ่งเป็นตัวโหลดคลาสแบบกำหนดเองซึ่งมีซอร์สโค้ดอยู่ในโปรเจ็กต์ GitHub ด้วยและฉันจะอธิบายรายละเอียดด้านล่าง



นี่คือส่วนที่เหลือของ main วิธี:

out.println('Seems to be the same class:'); out.println(userClass1.getName()); out.println(userClass2.getName()); out.println(); out.println('But why there are 2 different class loaders:'); out.println(userClass1.getClassLoader()); out.println(userClass2.getClassLoader()); out.println(); User.age = 11; out.println('And different age values:'); out.println((int) ReflectUtil.getStaticFieldValue('age', userClass1)); out.println((int) ReflectUtil.getStaticFieldValue('age', userClass2)); }

และผลลัพธ์:



Seems to be the same class: qj.blog.classreloading.example1.StaticInt$User qj.blog.classreloading.example1.StaticInt$User But why there are 2 different class loaders: [email protected] [email protected] And different age values: 11 10

ดังที่คุณเห็นที่นี่แม้ว่า User คลาสมีชื่อเดียวกันจริงๆแล้วเป็นคลาสสองคลาสที่แตกต่างกันและสามารถจัดการและจัดการได้อย่างอิสระ ค่าอายุแม้ว่าจะประกาศเป็นแบบคงที่ แต่ก็มีอยู่ในสองเวอร์ชันโดยแนบแยกกันกับแต่ละคลาสและสามารถเปลี่ยนแปลงได้อย่างอิสระเช่นกัน

วิธีออกแบบเว็บไซต์ shopify

ในโปรแกรม Java ปกติ ClassLoader เป็นพอร์ทัลที่นำคลาสเข้าสู่ JVM เมื่อคลาสหนึ่งต้องการให้โหลดคลาสอื่นมันเป็นงานของ ClassLoader ที่จะโหลด



อย่างไรก็ตามในตัวอย่างคลาส Java นี้กำหนดเอง ClassLoader ชื่อ DynamicClassLoader ใช้เพื่อโหลด User เวอร์ชันที่สอง ชั้นเรียน. ถ้าแทนที่จะเป็น DynamicClassLoader เราต้องใช้ตัวโหลดคลาสเริ่มต้นอีกครั้ง (ด้วยคำสั่ง StaticInt.class.getClassLoader()) แล้วเหมือนกัน User จะใช้คลาสเนื่องจากคลาสที่โหลดทั้งหมดจะถูกแคช

การตรวจสอบวิธีการทำงานของ Java ClassLoader เริ่มต้นเมื่อเทียบกับ DynamicClassLoader เป็นกุญแจสำคัญในการได้รับประโยชน์จากบทช่วยสอนคลาส Java นี้



DynamicClassLoader

สามารถมีหลาย classloaders ในโปรแกรม Java ปกติ อันที่โหลดคลาสหลักของคุณ ClassLoader เป็นคลาสเริ่มต้นและจากโค้ดของคุณคุณสามารถสร้างและใช้ตัวโหลดคลาสได้มากเท่าที่คุณต้องการ นี่คือกุญแจสำคัญในการโหลดคลาสใน Java DynamicClassLoader อาจเป็นส่วนที่สำคัญที่สุดของบทช่วยสอนทั้งหมดนี้ดังนั้นเราต้องเข้าใจว่าการโหลดคลาสแบบไดนามิกทำงานอย่างไรก่อนที่เราจะบรรลุเป้าหมาย

ซึ่งแตกต่างจากพฤติกรรมเริ่มต้นของ ClassLoader DynamicClassLoader ของเรา สืบทอดกลยุทธ์เชิงรุกมากขึ้น classloader ปกติจะให้พาเรนต์ ClassLoader ลำดับความสำคัญและโหลดเฉพาะคลาสที่พาเรนต์ไม่สามารถโหลดได้ ซึ่งเหมาะสำหรับสถานการณ์ปกติ แต่ไม่ใช่ในกรณีของเรา แทน DynamicClassLoader จะพยายามตรวจสอบพา ธ คลาสทั้งหมดและแก้ไขคลาสเป้าหมายก่อนที่จะให้สิทธิ์กับพาเรนต์

ในตัวอย่างของเราด้านบน DynamicClassLoader ถูกสร้างขึ้นด้วยพา ธ คลาสเดียวเท่านั้น: 'target/classes' (ในไดเรกทอรีปัจจุบันของเรา) ดังนั้นจึงสามารถโหลดคลาสทั้งหมดที่อยู่ในตำแหน่งนั้นได้ สำหรับคลาสทั้งหมดที่ไม่ได้อยู่ในนั้นจะต้องอ้างถึงตัวโหลดคลาสหลัก ตัวอย่างเช่นเราต้องโหลด String คลาสใน StaticInt ของเรา คลาสและตัวโหลดคลาสของเราไม่สามารถเข้าถึง rt.jar ในโฟลเดอร์ JRE ของเราดังนั้น String คลาสของตัวโหลดคลาสพาเรนต์จะถูกใช้

รหัสต่อไปนี้มาจาก AggressiveClassLoader คลาสพาเรนต์ของ DynamicClassLoader และแสดงว่าพฤติกรรมนี้ถูกกำหนดไว้ที่ใด

byte[] newClassData = loadNewClass(name); if (newClassData != null) { loadedClasses.add(name); return loadClass(newClassData, name); } else { unavaiClasses.add(name); return parent.loadClass(name); }

จดคุณสมบัติดังต่อไปนี้ของ DynamicClassLoader:

  • คลาสที่โหลดมีประสิทธิภาพและแอ็ตทริบิวต์อื่น ๆ เหมือนกับคลาสอื่น ๆ ที่โหลดโดยคลาสดีฟอลต์โหลด
  • DynamicClassLoader สามารถรวบรวมขยะร่วมกับคลาสและอ็อบเจ็กต์ที่โหลดทั้งหมด

ด้วยความสามารถในการโหลดและใช้คลาสเดียวกันสองเวอร์ชันตอนนี้เรากำลังคิดที่จะทิ้งเวอร์ชันเก่าและโหลดเวอร์ชันใหม่มาแทนที่ ในตัวอย่างต่อไปเราจะทำอย่างนั้น…อย่างต่อเนื่อง

ตัวอย่างที่ 2: การโหลดคลาสซ้ำอย่างต่อเนื่อง

ตัวอย่าง Java ต่อไปนี้จะแสดงให้คุณเห็นว่า JRE สามารถโหลดและรีโหลดคลาสได้ตลอดไปโดยคลาสเก่าจะถูกทิ้งและรวบรวมขยะและคลาสใหม่ล่าสุดที่โหลดจากฮาร์ดไดรฟ์และนำไปใช้งาน นี่คือซอร์สโค้ด

นี่คือลูปหลัก:

public static void main(String[] args) { for (;;) { Class userClass = new DynamicClassLoader('target/classes') .load('qj.blog.classreloading.example2.ReloadingContinuously$User'); ReflectUtil.invokeStatic('hobby', userClass); ThreadUtil.sleep(2000); } }

ทุกสองวินาทีเก่า User คลาสจะถูกถ่ายโอนคลาสใหม่จะถูกโหลดและวิธีการ hobby เรียก

นี่คือ User นิยามคลาส:

@SuppressWarnings('UnusedDeclaration') public static class User { public static void hobby() { playFootball(); // will comment during runtime // playBasketball(); // will uncomment during runtime } // will comment during runtime public static void playFootball() { System.out.println('Play Football'); } // will uncomment during runtime // public static void playBasketball() { // System.out.println('Play Basketball'); // } }

เมื่อเรียกใช้แอปพลิเคชันนี้คุณควรพยายามแสดงความคิดเห็นและยกเลิกการใส่ความคิดเห็นรหัสที่ระบุใน User ชั้นเรียน. คุณจะเห็นว่าคำจำกัดความใหม่ล่าสุดจะถูกใช้เสมอ

นี่คือผลลัพธ์ตัวอย่างบางส่วน:

... Play Football Play Football Play Football Play Basketball Play Basketball Play Basketball

ทุกครั้งที่มีการสร้าง DynamicClassLoader ถูกสร้างขึ้นมันจะโหลด User คลาสจาก target/classes ซึ่งเราได้ตั้งค่า Eclipse หรือ IntelliJ เพื่อส่งออกไฟล์คลาสล่าสุด เก่าทั้งหมด DynamicClassLoader s และเก่า User ชั้นเรียนจะถูกยกเลิกการเชื่อมโยงและอยู่ภายใต้การรวบรวมขยะ

จำเป็นอย่างยิ่งที่นักพัฒนา Java ขั้นสูงจะต้องเข้าใจการรีโหลดคลาสแบบไดนามิกไม่ว่าจะแอ็คทีฟหรือยกเลิกการลิงก์

หากคุณคุ้นเคยกับ JVM HotSpot เป็นที่น่าสังเกตว่าโครงสร้างคลาสสามารถเปลี่ยนแปลงและโหลดซ้ำได้เช่นกัน: the playFootball วิธีการคือการลบและ playBasketball เพิ่มวิธีการแล้ว สิ่งนี้แตกต่างจาก HotSpot ซึ่งอนุญาตให้เปลี่ยนเนื้อหาเมธอดเท่านั้นหรือไม่สามารถโหลดคลาสซ้ำได้

ตอนนี้เราสามารถโหลดคลาสซ้ำได้แล้วก็ถึงเวลาลองโหลดคลาสหลาย ๆ คลาสพร้อมกัน ลองดูในตัวอย่างถัดไป

ตัวอย่างที่ 3: การโหลดซ้ำหลายชั้น

ผลลัพธ์ของตัวอย่างนี้จะเหมือนกันกับตัวอย่างที่ 2 แต่จะแสดงวิธีการนำลักษณะการทำงานนี้ไปใช้ในโครงสร้างที่คล้ายแอปพลิเคชันมากขึ้นโดยมีบริบทบริการและวัตถุแบบจำลอง ซอร์สโค้ดของตัวอย่างนี้มีขนาดค่อนข้างใหญ่ดังนั้นฉันจึงแสดงเพียงบางส่วนเท่านั้นที่นี่ ซอร์สโค้ดแบบเต็มคือ ที่นี่ .

นี่คือ main วิธี:

public static void main(String[] args) { for (;;) { Object context = createContext(); invokeHobbyService(context); ThreadUtil.sleep(2000); } }

และวิธีการ createContext:

private static Object createContext() { Class contextClass = new DynamicClassLoader('target/classes') .load('qj.blog.classreloading.example3.ContextReloading$Context'); Object context = newInstance(contextClass); invoke('init', context); return context; }

วิธีการ invokeHobbyService:

private static void invokeHobbyService(Object context) { Object hobbyService = getFieldValue('hobbyService', context); invoke('hobby', hobbyService); }

และนี่คือ Context ชั้น:

public static class Context { public HobbyService hobbyService = new HobbyService(); public void init() { // Init your services here hobbyService.user = new User(); } }

และ HobbyService ชั้น:

public static class HobbyService { public User user; public void hobby() { user.hobby(); } }

Context คลาสในตัวอย่างนี้ซับซ้อนกว่า User มาก คลาสในตัวอย่างก่อนหน้านี้มีลิงก์ไปยังคลาสอื่นและมี init วิธีการที่จะเรียกว่าทุกมันเป็นอินสแตนซ์ โดยพื้นฐานแล้วจะคล้ายกับคลาสบริบทของแอปพลิเคชันในโลกแห่งความเป็นจริงมาก (ซึ่งจะติดตามโมดูลของแอปพลิเคชันและทำการแทรกการพึ่งพา) ดังนั้นความสามารถในการโหลดสิ่งนี้ใหม่ Context การเรียนร่วมกับคลาสที่เชื่อมโยงกันทั้งหมดเป็นขั้นตอนที่ยอดเยี่ยมในการนำเทคนิคนี้ไปใช้กับชีวิตจริง

การโหลดคลาส Java ซ้ำเป็นเรื่องยากสำหรับวิศวกร Java ขั้นสูง

เมื่อคลาสและออบเจ็กต์มีจำนวนมากขึ้นขั้นตอน 'ทิ้งเวอร์ชันเก่า' ของเราก็จะซับซ้อนขึ้นเช่นกัน นี่เป็นเหตุผลที่ใหญ่ที่สุดว่าทำไมการโหลดคลาสใหม่จึงยากมาก หากต้องการทิ้งเวอร์ชันเก่าเราจะต้องตรวจสอบให้แน่ใจว่าเมื่อสร้างบริบทใหม่แล้ว ทั้งหมด การอ้างอิงถึงคลาสเก่าและอ็อบเจ็กต์ถูกทิ้ง เราจะจัดการกับสิ่งนี้อย่างสง่างามได้อย่างไร?

main วิธีการที่นี่จะมีวัตถุบริบทค้างไว้และ นั่นคือลิงค์เดียว กับทุกสิ่งที่ต้องทิ้ง ถ้าเราทำลายลิงก์นั้นอ็อบเจ็กต์บริบทและคลาสบริบทและเซอร์วิสอ็อบเจ็กต์ ... ทั้งหมดจะถูกเก็บรวบรวมขยะ

คำอธิบายเล็กน้อยเกี่ยวกับสาเหตุที่ชั้นเรียนปกติมีอยู่อย่างต่อเนื่องและไม่ได้รับการเก็บรวบรวมขยะ:

  • โดยปกติเราโหลดคลาสทั้งหมดของเราลงใน Java classloader เริ่มต้น
  • ความสัมพันธ์ class-classloader เป็นความสัมพันธ์แบบสองทางโดย class loader จะแคชคลาสทั้งหมดที่โหลดไว้ด้วย
  • ตราบใดที่ classloader ยังคงเชื่อมต่อกับเธรดสดทุกอย่าง (คลาสที่โหลดทั้งหมด) จะไม่ได้รับผลกระทบจากตัวเก็บขยะ
  • ที่กล่าวว่าเว้นแต่เราสามารถแยกรหัสที่เราต้องการโหลดซ้ำจากโค้ดที่โหลดโดยตัวโหลดคลาสเริ่มต้นแล้วการเปลี่ยนแปลงโค้ดใหม่ของเราจะไม่ถูกนำไปใช้ในระหว่างรันไทม์

จากตัวอย่างนี้เราจะเห็นว่าการโหลดคลาสของแอปพลิเคชันทั้งหมดซ้ำนั้นค่อนข้างง่าย เป้าหมายเป็นเพียงเพื่อให้การเชื่อมต่อที่บางและหยดได้จากเธรดสดไปยังตัวโหลดคลาสไดนามิกที่ใช้งานอยู่ แต่ถ้าเราต้องการให้วัตถุบางอย่าง (และคลาสของพวกเขา) เป็นอย่างไร ไม่ ต้องโหลดซ้ำและนำมาใช้ซ้ำระหว่างรอบการโหลดซ้ำ? ลองดูตัวอย่างถัดไป

ตัวอย่างที่ 4: การแยกพื้นที่คลาสที่ยังคงอยู่และโหลดซ้ำ

นี่คือซอร์สโค้ด .

main วิธี:

public static void main(String[] args) { ConnectionPool pool = new ConnectionPool(); for (;;) { Object context = createContext(pool); invokeService(context); ThreadUtil.sleep(2000); } }

ดังนั้นคุณจะเห็นว่าเคล็ดลับที่นี่คือการโหลด ConnectionPool คลาสและสร้างอินสแตนซ์นอกวงจรการโหลดซ้ำโดยเก็บไว้ในช่องว่างที่คงอยู่และส่งต่อการอ้างอิงไปยัง Context วัตถุ

createContext วิธีการก็แตกต่างกันเล็กน้อย:

private static Object createContext(ConnectionPool pool) { ExceptingClassLoader classLoader = new ExceptingClassLoader( (className) -> className.contains('.crossing.'), 'target/classes'); Class contextClass = classLoader.load('qj.blog.classreloading.example4.reloadable.Context'); Object context = newInstance(contextClass); setFieldValue(pool, 'pool', context); invoke('init', context); return context; }

จากนี้ไปเราจะเรียกอ็อบเจ็กต์และคลาสที่โหลดซ้ำทุก ๆ รอบว่า 'พื้นที่ที่โหลดซ้ำได้' และอื่น ๆ - อ็อบเจ็กต์และคลาสที่ไม่ได้รีไซเคิลและไม่ได้รับการต่ออายุในระหว่างรอบการโหลดซ้ำ - เราจะต้องชัดเจนมากว่าวัตถุหรือคลาสใดอยู่ในช่องว่างใดจึงลากเส้นแยกระหว่างช่องว่างทั้งสองนี้

หากไม่ได้รับการจัดการอย่างเหมาะสมการแยกการโหลดคลาส Java นี้อาจทำให้เกิดความล้มเหลว

ดังที่เห็นจากภาพไม่เพียง แต่เป็น Context วัตถุและ UserService วัตถุที่อ้างถึง ConnectionPool วัตถุ แต่ Context และ UserService ชั้นเรียนยังอ้างถึง ConnectionPool ชั้นเรียน. นี่เป็นสถานการณ์ที่อันตรายมากซึ่งมักนำไปสู่ความสับสนและความล้มเหลว ConnectionPool ต้องไม่โหลดโดย DynamicClassLoader ของเราต้องมีเพียงหนึ่งเดียว ConnectionPool คลาสในหน่วยความจำซึ่งเป็นคลาสที่โหลดโดยค่าเริ่มต้น ClassLoader นี่เป็นตัวอย่างหนึ่งที่แสดงให้เห็นว่าทำไมการออกแบบสถาปัตยกรรมการรีโหลดคลาสใน Java จึงสำคัญมาก

จะเกิดอะไรขึ้นถ้า DynamicClassLoader ของเรา โดยบังเอิญโหลด ConnectionPool ชั้น? จากนั้น ConnectionPool ไม่สามารถส่งผ่านวัตถุจากช่องว่างที่มีอยู่ไปยัง Context วัตถุเนื่องจาก Context ออบเจ็กต์คาดหวังว่าออบเจ็กต์ของคลาสอื่นซึ่งมีชื่อว่า ConnectionPool แต่จริงๆแล้วเป็นคลาสอื่น!

ดังนั้นเราจะป้องกัน DynamicClassLoader ของเราได้อย่างไร จากการโหลด ConnectionPool ชั้น? แทนที่จะใช้ DynamicClassLoader ตัวอย่างนี้ใช้คลาสย่อยของมันชื่อ: ExceptingClassLoader ซึ่งจะส่งผ่านการโหลดไปยัง super classloader ตามฟังก์ชันเงื่อนไข:

(className) -> className.contains('$Connection')

ถ้าเราไม่ใช้ ExceptingClassLoader ที่นี่แล้ว DynamicClassLoader จะโหลด ConnectionPool ชั้นเรียนเพราะชั้นเรียนนั้นอยู่ในส่วน“ target/classes” โฟลเดอร์ อีกวิธีหนึ่งในการป้องกัน ConnectionPool DynamicClassLoader ของเรามารับชั้นเรียน คือการรวบรวม ConnectionPool คลาสไปยังโฟลเดอร์อื่นอาจอยู่ในโมดูลอื่นและจะถูกคอมไพล์แยกกัน

กฎสำหรับการเลือกพื้นที่

ตอนนี้งานโหลดคลาส Java เริ่มสับสนมาก เราจะพิจารณาได้อย่างไรว่าคลาสใดควรอยู่ในพื้นที่คงอยู่และคลาสใดในพื้นที่ที่โหลดซ้ำได้ นี่คือกฎ:

  1. คลาสในพื้นที่ที่โหลดซ้ำได้อาจอ้างอิงคลาสในพื้นที่คงอยู่ แต่คลาสในพื้นที่คงอยู่ อาจไม่เคย อ้างอิงคลาสในพื้นที่ที่โหลดซ้ำได้ ในตัวอย่างก่อนหน้านี้รีโหลดได้ Context การอ้างอิงคลาสยังคงอยู่ ConnectionPool ชั้นเรียน แต่ ConnectionPool ไม่มีการอ้างอิงถึง Context
  2. คลาสสามารถมีอยู่ในช่องว่างใดพื้นที่หนึ่งถ้าไม่ได้อ้างอิงคลาสใด ๆ ในพื้นที่อื่น ตัวอย่างเช่นคลาสยูทิลิตี้ที่มีวิธีการคงที่ทั้งหมดเช่น StringUtils สามารถโหลดได้ครั้งเดียวในพื้นที่คงอยู่และโหลดแยกกันในพื้นที่ที่โหลดซ้ำได้

ดังนั้นคุณจะเห็นว่ากฎไม่ได้มีข้อ จำกัด มากนัก ยกเว้นคลาสข้ามที่มีอ็อบเจ็กต์อ้างอิงข้ามทั้งสองช่องว่างคลาสอื่น ๆ ทั้งหมดสามารถใช้ได้อย่างอิสระทั้งในพื้นที่คงอยู่หรือพื้นที่ที่โหลดซ้ำได้หรือทั้งสองอย่าง แน่นอนว่ามีเพียงคลาสในพื้นที่ที่โหลดซ้ำได้เท่านั้นที่จะเพลิดเพลินกับการโหลดซ้ำด้วยรอบการโหลดซ้ำ

ดังนั้นปัญหาที่ท้าทายที่สุดในการรีโหลดคลาสจึงได้รับการจัดการ ในตัวอย่างถัดไปเราจะพยายามนำเทคนิคนี้ไปใช้กับเว็บแอปพลิเคชันง่ายๆและสนุกกับการโหลดคลาส Java ซ้ำเช่นเดียวกับภาษาสคริปต์

ตัวอย่างที่ 5: สมุดโทรศัพท์เล็ก ๆ น้อย ๆ

นี่คือซอร์สโค้ด .

ตัวอย่างนี้จะคล้ายกับลักษณะของเว็บแอปพลิเคชันทั่วไป เป็นแอปพลิเคชันหน้าเดียวที่มี AngularJS, SQLite, Maven และ Jetty Embedded Web Server .

นี่คือพื้นที่ที่โหลดซ้ำได้ในโครงสร้างของเว็บเซิร์ฟเวอร์:

ความเข้าใจอย่างถ่องแท้เกี่ยวกับพื้นที่ที่โหลดซ้ำได้ในโครงสร้างของเว็บเซิร์ฟเวอร์จะช่วยให้คุณเชี่ยวชาญในการโหลดคลาส Java

เว็บเซิร์ฟเวอร์จะไม่เก็บการอ้างอิงถึง servlets จริงซึ่งจะต้องอยู่ในพื้นที่ที่โหลดซ้ำได้เพื่อที่จะโหลดซ้ำ สิ่งที่เก็บไว้คือ Stub servlets ซึ่งทุกครั้งที่เรียกใช้เมธอดเซอร์วิสจะแก้ไข servlet จริงในบริบทจริงเพื่อรัน

ตัวอย่างนี้ยังแนะนำอ็อบเจ็กต์ใหม่ ReloadingWebContext ซึ่งจัดเตรียมค่าทั้งหมดให้กับเว็บเซิร์ฟเวอร์เช่นบริบทปกติ แต่ภายในจะเก็บการอ้างอิงไปยังอ็อบเจ็กต์บริบทจริงที่สามารถโหลดซ้ำได้โดย DynamicClassLoader มันคือ ReloadingWebContext ซึ่งให้บริการที่สมบูรณ์แก่เว็บเซิร์ฟเวอร์

ReloadingWebContext จัดการกับ Stub servlets ไปยังเว็บเซิร์ฟเวอร์ในกระบวนการรีโหลดคลาส Java

ReloadingWebContext จะเป็นตัวห่อของบริบทจริงและ:

  • จะโหลดบริบทจริงซ้ำเมื่อมีการเรียก HTTP GET to“ /”
  • จะให้บริการที่สมบูรณ์แก่เว็บเซิร์ฟเวอร์
  • จะกำหนดค่าและเรียกใช้วิธีการทุกครั้งที่บริบทจริงเริ่มต้นหรือถูกทำลาย
  • สามารถกำหนดค่าให้โหลดบริบทใหม่หรือไม่และ classloader ใดที่ใช้ในการโหลดซ้ำ สิ่งนี้จะช่วยเมื่อเรียกใช้แอปพลิเคชันในการผลิต

เนื่องจากเป็นสิ่งสำคัญมากที่จะต้องทำความเข้าใจว่าเราแยกพื้นที่ที่มีอยู่และพื้นที่ที่โหลดซ้ำได้อย่างไรต่อไปนี้คือคลาสสองคลาสที่ข้ามระหว่างช่องว่างทั้งสอง:

ชั้น qj.util.funct.F0 สำหรับวัตถุ public F0 connF ใน Context

  • วัตถุฟังก์ชันจะส่งคืนการเชื่อมต่อทุกครั้งที่เรียกใช้ฟังก์ชัน คลาสนี้อยู่ในแพ็คเกจ qj.util ซึ่งไม่รวมอยู่ใน DynamicClassLoader

ชั้น java.sql.Connection สำหรับวัตถุ public F0 connF ใน Context

  • วัตถุการเชื่อมต่อ SQL ปกติ คลาสนี้ไม่ได้อยู่ในพา ธ ของคลาส DynamicClassLoader ของเราดังนั้นคลาสนี้จะไม่ถูกเลือก

สรุป

ในบทช่วยสอนคลาส Java นี้เราได้เห็นวิธีการโหลดคลาสเดียวโหลดคลาสเดียวซ้ำอย่างต่อเนื่องโหลดพื้นที่ทั้งหมดของคลาสหลายคลาสและรีโหลดคลาสหลายคลาสแยกจากคลาสที่ต้องคงอยู่ ด้วยเครื่องมือเหล่านี้ปัจจัยสำคัญในการรีโหลดคลาสที่เชื่อถือได้คือการออกแบบที่ดูสะอาดตา จากนั้นคุณสามารถจัดการชั้นเรียนของคุณและ JVM ทั้งหมดได้อย่างอิสระ

การนำคลาส Java มาใช้ซ้ำไม่ใช่สิ่งที่ง่ายที่สุดในโลก แต่ถ้าคุณลองยิงและเมื่อถึงจุดหนึ่งพบว่าชั้นเรียนของคุณถูกโหลดทันทีแสดงว่าคุณเกือบจะอยู่ที่นั่นแล้ว จะเหลือน้อยมากที่จะทำก่อนที่คุณจะได้รับการออกแบบที่ยอดเยี่ยมโดยสิ้นเชิงสำหรับระบบของคุณ

ขอให้โชคดีเพื่อน ๆ และสนุกไปกับพลังพิเศษที่เพิ่งค้นพบ

แนวทางปฏิบัติที่ดีที่สุดของ M&A ในละตินอเมริกา

กระบวนการทางการเงิน

แนวทางปฏิบัติที่ดีที่สุดของ M&A ในละตินอเมริกา
Wireframe Mapping: วิธีหลีกเลี่ยง Scope Lag

Wireframe Mapping: วิธีหลีกเลี่ยง Scope Lag

การออกแบบ Ux

โพสต์ยอดนิยม
ความจริงเสมือนในอุตสาหกรรมยานยนต์
ความจริงเสมือนในอุตสาหกรรมยานยนต์
วิธีใช้ Bootstrap และสร้าง. NET Projects
วิธีใช้ Bootstrap และสร้าง. NET Projects
วิธีทำความเข้าใจและประเมินการลงทุนในกองทุนอสังหาริมทรัพย์ส่วนบุคคล
วิธีทำความเข้าใจและประเมินการลงทุนในกองทุนอสังหาริมทรัพย์ส่วนบุคคล
4 ไปวิจารณ์ภาษา
4 ไปวิจารณ์ภาษา
ข้อมูลเบื้องต้นเกี่ยวกับ Magento: การนำทางในระบบนิเวศอีคอมเมิร์ซยอดนิยม
ข้อมูลเบื้องต้นเกี่ยวกับ Magento: การนำทางในระบบนิเวศอีคอมเมิร์ซยอดนิยม
 
วีซ่า H-1B: การเดินทางของนักพัฒนา iOS จากฮอนดูรัสไปยัง Silicon Valley
วีซ่า H-1B: การเดินทางของนักพัฒนา iOS จากฮอนดูรัสไปยัง Silicon Valley
ข้อผิดพลาดทั่วไปในการสื่อสารกับลูกค้า: จะไม่ทำให้ลูกค้าของคุณผิดหวังได้อย่างไร
ข้อผิดพลาดทั่วไปในการสื่อสารกับลูกค้า: จะไม่ทำให้ลูกค้าของคุณผิดหวังได้อย่างไร
การออกแบบที่คาดหวัง: วิธีสร้างประสบการณ์ผู้ใช้ที่มีมนต์ขลัง
การออกแบบที่คาดหวัง: วิธีสร้างประสบการณ์ผู้ใช้ที่มีมนต์ขลัง
กราฟิก 3 มิติ: บทช่วยสอน WebGL
กราฟิก 3 มิติ: บทช่วยสอน WebGL
การออกแบบ VUI - Voice User Interface
การออกแบบ VUI - Voice User Interface
โพสต์ยอดนิยม
  • ข้อใดไม่ใช่หลักการออกแบบ
  • วิธีใช้บอทดิสคอร์ด
  • ทำไมบริษัทถึงป้องกันความเสี่ยงจากอัตราแลกเปลี่ยน
  • เปลี่ยนตัวแปร css ด้วย javascript
  • git flow เทียบกับ github flow
  • ผลกระทบทางจิตวิทยาของสีฟ้า
หมวดหมู่
  • การเพิ่มขึ้นของระยะไกล
  • ผู้คนและทีมงาน
  • การวางแผนและการพยากรณ์
  • การออกแบบ Ux
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt