מבוא לפרויקט פאזל

1. הקדמה

Project Jigsaw הוא פרויקט גג עם התכונות החדשות המכוונות לשני היבטים:

  • הכנסת מערכת המודולים בשפת Java
  • והטמעתו במקור JDK ובזמן ריצה של Java

במאמר זה נציג בפניכם את פרויקט פאזל ותכונותיו ולסיום נסכם אותו ביישום מודולרי פשוט.

2. מודולריות

במילים פשוטות, מודולריות היא עקרון עיצובי שעוזר לנו להשיג:

  • צימוד רופף בין רכיבים
  • ברור חוזים ותלות בין רכיבים
  • יישום נסתר באמצעות אנקפסולציה חזקה

2.1. יחידת מודולריות

כעת עולה השאלה מהי יחידת המודולריות? בעולם הג'אווה, במיוחד עם OSGi, JARs נחשבו כיחידת המודולריות.

JARs עזרו בקיבוץ המרכיבים הקשורים יחד, אך יש להם מגבלות מסוימות:

  • חוזים ותלות מפורשים בין JAR
  • אנקפסציה חלשה של אלמנטים בתוך ה- JAR

2.2. JAR לעזאזל

הייתה בעיה נוספת עם JAR - לעזאזל ה- JAR. גרסאות מרובות של ה- JAR המונחות על שביל הכיתה, הביאו לכך שה- JAR ClassLoader טוען את הכיתה שנמצאה הראשונה מה- JAR, עם תוצאות מאוד לא צפויות.

הבעיה האחרת עם ה- JVM באמצעות מסלול הכיתה הייתה כי אוסף היישום יצליח, אך היישום ייכשל בזמן הריצה עם ClassNotFoundException, בגלל ה- JAR חסרים בשביל הכיתה בזמן הריצה.

2.3. יחידה חדשה של מודולריות

עם כל המגבלות הללו, כאשר השתמשו ב- JAR כיחידת המודולריות, יוצרי שפת Java העלו מבנה חדש בשפה הנקראת מודולים. ועם זה מתוכננת מערכת Java חדשה לגמרי.

3. פאזל פרוייקט

המניעים העיקריים לפרויקט זה הם:

  • ליצור מערכת מודול לשפה - מיושם תחת JEP 261
  • החל אותו על מקור ה- JDK - מיושם תחת JEP 201
  • לשנות את ה- JDKספריות - מיושם תחת JEP 200
  • עדכן את זמן הריצה כדי לתמוך במודולריות - מיושם תחת JEP 220
  • להיות מסוגל ליצור זמן ריצה קטן יותר עם תת קבוצה של מודולים מ- JDK - מיושם לפי JEP 282

יוזמה חשובה נוספת היא לכמוס את ה- APIs הפנימיים ב- JDK, אלה שנמצאים תחת ה- שמש.* חבילות וממשקי API אחרים שאינם סטנדרטיים. ממשקי API אלה מעולם לא נועדו לשמש את הציבור ומעולם לא תוכננו לתחזק אותם. אך הכוח של ממשקי ה- API הללו גרם למפתחי Java למנף אותם בפיתוח ספריות, מסגרות וכלים שונים. היו תחליפים שסופקו למעט ממשקי API פנימיים והאחרים הועברו למודולים פנימיים.

4. כלים חדשים למודולריות

  • jdeps - מסייע בניתוח בסיס הקוד לזיהוי התלות ב- API של JDK וב- JAR של צד שלישי. זה מציין גם את שם המודול שבו ניתן למצוא את ה- JDK API. זה מקל על המודולריזציה של בסיס הקוד
  • jdeprscan - מסייע בניתוח בסיס הקוד לשימוש בכל ממשקי API שהוצאו משימוש
  • jlink - מסייע ביצירת זמן ריצה קטן יותר על ידי שילוב של האפליקציות והמודולים של JDK
  • jmod - עוזר בעבודה עם קבצי jmod. jmod הוא פורמט חדש לאריזת המודולים. פורמט זה מאפשר לכלול קוד מקורי, קבצי תצורה ונתונים אחרים שאינם נכנסים לקבצי JAR

5. אדריכלות מערכת מודול

מערכת המודולים, המיושמת בשפה, תומכת בהם כמבנה ברמה עליונה, ממש כמו חבילות. מפתחים יכולים לארגן את הקוד שלהם במודולים ולהצהיר על תלות ביניהם בקבצי הגדרת המודול שלהם.

קובץ הגדרת מודול, בשם module-info.java, מכיל:

  • שמו
  • את החבילות שהוא מגיש לציבור
  • את המודולים שזה תלוי בהם
  • כל השירותים שהוא צורך
  • כל יישום לשירות שהוא מספק

לא משתמשים בשני הפריטים האחרונים ברשימה שלעיל. הם משמשים רק כאשר השירותים ניתנים ונצרכים באמצעות java.util.ServiceLoader מִמְשָׁק.

מבנה כללי של המודול נראה כמו:

src | ---- com.baeldung.reader | | ---- module-info.java | | ---- com | | ---- באלדונג | | ---- קורא | | ---- Test.java | ---- com.baeldung.writer | ---- module-info.java | ---- com | ---- baeldung | ---- סופר | --- -AnotherTest.java

האיור לעיל מגדיר שני מודולים: com.baeldung.reader ו com.baeldung.writer. להגדרה של כל אחד מהם מוגדרת ב module-info.java ואת קבצי הקוד שהונחו תחת com / baeldung / reader ו com / baeldung / סופרת, בהתאמה.

5.1. מינוחי הגדרת מודול

הבה נבחן כמה מהטרמינולוגיות; נשתמש בה בעת הגדרת המודול (כלומר בתוך module-info.java):

  • מודול: קובץ הגדרת המודול מתחיל במילת מפתח זו ואחריה שמו והגדרתו
  • דורש: משמש לציון המודולים שהוא תלוי בהם; יש לציין שם מודול אחרי מילת מפתח זו
  • מעבר: מוגדר לאחר דורש מילת מפתח; פירוש הדבר שכל מודול שתלוי בהגדרת המודול דורש מעבר מקבל תלות מרומזת ב- <modulename>
  • יצוא: משמש לציין את החבילות במודול הזמינות באופן ציבורי; יש לציין שם חבילה אחרי מילת מפתח זו
  • נפתח: משמש לציין את החבילות הנגישות רק בזמן ריצה וזמינות גם למבט פנימי באמצעות ממשקי API של Reflection; זה די משמעותי לספריות כמו Spring ו- Hibernate, מאוד מסתמכות על ממשקי API של Reflection; נפתח יכול לשמש גם ברמת המודול ובמקרה כזה המודול כולו נגיש בזמן ריצה
  • שימושים: משמש לציון ממשק השירות בו משתמש מודול זה; יש לציין שם סוג, כלומר שם מחלקה / ממשק שלם, לאחר מילת מפתח זו
  • מספק ... עם ...: הם משמשים כדי לציין שהוא מספק יישומים, שזוהו לאחר עם מילת מפתח, עבור ממשק השירות שזוהה לאחר מספק מילת מפתח

6. יישום מודולרי פשוט

הבה ניצור יישום מודולרי פשוט עם מודולים ותלותיהם כפי שמצוין בתרשים להלן:

ה com.baeldung.student.model הוא מודול השורש. זה מגדיר מעמד מודל com.baeldung.student.model.Student, המכיל את המאפיינים הבאים:

כיתה ציבורית סטודנט {private String registrationId; // שדות רלוונטיים אחרים, גטרים וקובעים}

הוא מספק מודולים אחרים עם סוגים המוגדרים ב- com.baeldung.student.model חֲבִילָה. זה מושג על ידי הגדרתו בקובץ module-info.java:

מודול com.baeldung.student.model {יצוא com.baeldung.student.model; }

ה com.baeldung.student.service המודול מספק ממשק com.baeldung.student.service.StudentService עם פעולות CRUD מופשטות:

ממשק ציבורי StudentService {public String create (סטודנט סטודנט); קריאת סטודנטים ציבורית (רישום מחרוזת מזהה); עדכון סטודנטים ציבורי (סטודנט סטודנט); מחיקת מחרוזת ציבורית (רישום מזהה מחרוזת); }

זה תלוי ב com.baeldung.student.model מודול והופך את הסוגים המוגדרים בחבילה com.baeldung.student.service זמין עבור מודולים אחרים:

מודול com.baeldung.student.service {דורש com.baeldung.student.model מעבר; יצוא com.baeldung.student.service; }

אנו מספקים מודול נוסף com.baeldung.student.service.dbimpl, המספק את היישום com.baeldung.student.service.dbimpl.StudentDbService עבור המודול הנ"ל:

מחלקה ציבורית StudentDbService מיישמת את StudentService {public String create (סטודנט סטודנט) {// יצירת תלמיד ב- DB מחזירה student.getRegistrationId (); } קריאת סטודנטים ציבורית (String registrationId) {// סטודנט קריאה מ- DB מחזיר סטודנט חדש (); } עדכון סטודנטים ציבורי (סטודנט סטודנט) {// מעדכן סטודנט בתלמיד חוזר ל- DB; } מחיקת מחרוזות ציבורית (String registrationId) {// מחיקת סטודנט ב- DB החזרת registryId; }}

זה תלוי ישירות ב com.baeldung.student.service ובמעבר הלאה com.baeldung.student.model והגדרתו תהיה:

מודול com.baeldung.student.service.dbimpl {דורש com.baeldung.student.service מעבר. דורש java.logging; יצוא com.baeldung.student.service.dbimpl; }

המודול הסופי הוא מודול לקוח - הממנף את מודול הטמעת השירות com.baeldung.student.service.dbimpl לביצוע פעולותיה:

מחלקה ציבורית StudentClient {public static void main (String [] args) {StudentService service = new StudentDbService (); service.create (סטודנט חדש ()); service.read ("17SS0001"); service.update (סטודנט חדש ()); service.delete ("17SS0001"); }}

והגדרתו היא:

מודול com.baeldung.student.client {דורש com.baeldung.student.service.dbimpl; }

7. קומפילציה והפעלת המדגם

סיפקנו סקריפטים להרכבה והפעלה של המודולים שלעיל עבור פלטפורמות Windows ו- Unix. אלה ניתן למצוא תחת core-java-9 פרויקט כאן. סדר הביצוע עבור פלטפורמת Windows הוא:

  1. הידור-סטודנט-מודל
  2. שירות קומפילציה-סטודנטים
  3. לקמפל-סטודנט-שירות-dbimpl
  4. לקטוף-תלמיד-לקוח
  5. לקוח תלמיד רץ

סדר הביצוע לפלטפורמת לינוקס הוא די פשוט:

  1. לקבץ-מודולים
  2. לקוח תלמיד רץ

בתסריטים שלמעלה, תוצג בפניך שני טיעוני שורת הפקודה הבאים:

  • –מודול-מקור-נתיב
  • –מודול-נתיב

Java 9 מבטל את המושג classpath ובמקום זאת מציג את נתיב המודול. נתיב זה הוא המיקום בו ניתן לגלות את המודולים.

אנו יכולים להגדיר זאת באמצעות הארגומנט של שורת הפקודה: –מודול-נתיב.

כדי להרכיב מספר מודולים בו זמנית, אנו משתמשים ב- –מודול-מקור-נתיב. ארגומנט זה משמש כדי לספק את המיקום עבור קוד המקור של המודול.

8. מערכת המודולים מוחלת על מקור ה- JDK

כל התקנת JDK מסופקת עם src.zip. ארכיון זה מכיל את בסיס הקוד של ממשקי ה- API של JDK Java. אם תוציאו את הארכיון, תמצאו מספר תיקיות, מעטות המתחילות בהן ג'אווה, מעטים עם javafx והשאר עם jdk. כל תיקיה מייצגת מודול.

המודולים החל מ- ג'אווה הם המודולים של JDK, אלה שמתחילים ב- javafx הם המודולים של JavaFX ואחרים החל מ jdk הם מודולי הכלים של JDK.

כל המודולים של JDK וכל המודולים המוגדרים על ידי המשתמש תלויים במשתמע java.base מודול. ה java.base המודול מכיל ממשקי API של JDK נפוצים כמו Utils, Collections, IO, Concurrency בין היתר. גרף התלות של מודולי JDK הוא:

אתה יכול גם להסתכל בהגדרות של מודולי JDK כדי לקבל מושג על התחביר להגדרת אותם ב module-info.java.

9. מסקנה

במאמר זה בדקנו יצירה, קומפילציה והפעלת יישום מודולרי פשוט. ראינו גם כיצד קוד המקור של JDK עבר מודולציה.

יש כמה תכונות מרגשות יותר, כמו יצירת זמן ריצה קטן יותר באמצעות כלי המקשר - jlink ויצירת צנצנות מודולריות בין שאר התכונות. אנו נציג בפניך את התכונות הללו בפרטים במאמרים עתידיים.

Project Jigsaw הוא שינוי עצום, ונצטרך לחכות ולראות כיצד הוא מתקבל על ידי המערכת האקולוגית של המפתחים, בפרט עם הכלים ויוצרי הספריות.

את הקוד המשמש במאמר זה ניתן למצוא באתר GitHub.