מהו אביב? פיתוח מבוסס רכיבים עבור Java

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

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

הזרקת תלות והיפוך שליטה

הרעיון המרכזי של אביב הוא שבמקום לנהל בעצמך יחסי אובייקט אתה מוריד אותם למסגרת. היפוך שליטה (IOC) הוא המתודולוגיה המשמשת לניהול יחסי אובייקט. הזרקת תלות היא המנגנון ליישום IOC. מכיוון ששני המושגים הללו קשורים אך שונים, הבה נבחן אותם מקרוב:

  • היפוך שליטה (IOC) עושה בדיוק את מה ששמו אומר: הוא הופך את ההיררכיה המסורתית של שליטה למימוש יחסי אובייקט. במקום להסתמך על קוד יישום כדי להגדיר את האופן שבו אובייקטים קשורים זה לזה, מערכות היחסים מוגדרות על ידי המסגרת. כמתודולוגיה, IOC מציג עקביות וחיזוי להתנגדות ביחסים, אך הוא מחייב אותך כמפתח לוותר על שליטה דקה.
  • הזרקת תלות (DI) היא מנגנון שבו המסגרת "מזריקה" תלות באפליקציה שלך. זה היישום המעשי של ה- IOC. הזרקת תלות תלויה בפולימורפיזם, במובן זה שהיא מאפשרת מימוש של סוג התייחסות לשינוי בהתבסס על תצורות במסגרת. המסגרת מזריקה הפניות משתנות במקום למלא אותן באופן ידני בקוד היישום.

JSR-330

כמו הרבה בעולם ג'אווה, מה שהתחיל כחידוש בטבע, אביב, נקלט בחלקו במפרט הסטנדרטי. במקרה זה, JSR-330 הוא תקן Java. הדבר הנחמד במפרט JSR-330 הוא שתוכל להשתמש בו במקום אחר, ותראה אותו בשימוש במקום אחר, מעבר לאביב. אתה יכול להשתמש בו מבלי להשתמש באביב. עם זאת, אביב מביא הרבה יותר לשולחן.

דוגמה מס '1: הזרקת תלות באביב

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

תגיד שאתה מדגמן מכונית. אם אתה מדגמן ב- Java ישנה רגילה, ייתכן שיהיה חבר ממשק Carבכיתה שיתייחס Engineלממשק, כפי שמוצג ברשימה 1.

רישום 1. יחסי אובייקט בג'אווה ישנה רגילה

 public Interface Engine() { ... } public class Car { private Engine engine; public Engine getEngine() { ... } public void setEngine(Engine engine) { ... } } 

רישום 1 מכיל ממשק Engineלסוג, ומחלקה Carלסוג הבטון , המפנה ל Engine. (שים לב שבתרחיש תכנות אמיתי אלה יהיו בקבצים נפרדים.) כעת, כאשר אתה יוצר Carמופע, היית מגדיר את השיוך כפי שמוצג ברשימה 2.

רישום 2. יצירת רכב עם ממשק המנוע

 // ... Car newCar = new Car(); Engine sixCylEngine = new InlineSixCylinderEngine(); newCar.setEngine(sixCylEngine ); // Do stuff with the car 

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

דוגמנות שיעורים וחפצים באביב

עכשיו בואו נסתכל על אותה דוגמא באביב. הנה, אתה יכול לעשות משהו כמו מה שמוצג מודעה 3. אתה מתחיל עם Carהכיתה, אבל במקרה הזה אתה מוסיף ביאור אליו: @Inject.

רישום 3. דוגמה לשימוש בהערת @Inject באביב

 public class Car { @Inject private Engine engine; // ... } 

שימוש @Injectבהערה (או @Autowired, אם אתה מעדיף) אומר לאביב לחפש את ההקשר ולהזריק אובייקט באופן אוטומטי להפניה, בהתבסס על מערכת כללים.

לאחר מכן שקול את @Componentההערה המוצגת ברשימה 4.

רישום 4. הערת @ רכיב

 @Component public class InlineSixCylinderEngine implements Engine{ //... } 

ביאור לשיעור איתו @Componentאומר לאביב שהוא זמין למימוש זריקות. במקרה זה, InlineSixCylEngineיוזרק כי הוא זמין ועונה על דרישת הממשק של העמותה. באביב זה נקרא זריקה "אוטומטית". (ראה להלן מידע נוסף על @Autowiredההערה של אביב ).

ניתוק כעקרון עיצובי

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

@Autowired לעומת @ Inject

@Autowiredו @Injectלעשות את אותו הדבר. עם זאת, @Injectההערה הסטנדרטית של Java @Autowiredהיא , ואילו היא ספציפית לאביב. שניהם משרתים את אותה מטרה לומר למנוע ה- DI להזריק את השדה או השיטה עם אובייקט תואם. אתה יכול להשתמש באחד מהם באביב.

סקירה של מסגרת האביב

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

  • מיכל ליבה
    • הליבה
    • אפונה
    • הֶקשֵׁר
    • שפת ביטוי
  • תכנות מונחה היבטים (AOP)
    • AOP
    • היבטים
    • מִכשׁוּר
  • גישה ושילוב נתונים
    • JDBC
    • JPA / ORM
    • JMS
    • עסקאות
  • אינטרנט
    • אינטרנט / מנוחה
    • סרוולט
    • תמוכות

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

הקמת פרויקט חדש: Spring Boot

נשתמש באביב אתחול כדי ליצור פרויקט לדוגמה, בו נשתמש להדגמת תכונות אביב. Spring Boot מקל על התחלת פרויקטים חדשים, כפי שתראו בעצמכם. כדי להתחיל, התבונן במחלקה הראשית המוצגת למטה. באביב אתחול, אנו יכולים לקחת מעמד ראשי main()בשיטה, ואז לבחור להפעיל אותו עצמאי, או לארוז לפריסה במיכל כמו Tomcat.

ברשימה 5 יש קווי מתאר של המעמד הראשי שלנו, שיחיה src/main/java/helloבמיקום הסטנדרטי .

רישום 5. מחלקה ראשית עם מגף אביב

 package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } 

שימו לב לשני דברים לגבי הקוד הנ"ל: ראשית, כל העבודות מופשטות למסגרת. המעמד הראשי מאתחל את האפליקציה, אך הוא אינו יודע דבר על האופן בו האפליקציה פועלת או מספקת את הפונקציונליות שלה. שנית, SpringApplication.run()זה עושה את העבודה בפועל לאתחל את האפליקציה ולעבור Applicationבכיתה עצמה. שוב, העבודה שהאפליקציה עושה אינה ניכרת כאן.

@SpringBootApplicationהביאור עוטף כמה בהערות סטנדרטיות ואומר אביב להסתכל על החבילה שבה המעמד המרכזי קיים עבור רכיבים. בדוגמה הקודמת שלנו, עם המכונית והמנוע, זה יאפשר לאביב למצוא את כל הכיתות המוערות עם @Componentו @Inject. התהליך עצמו, הנקרא סריקת רכיבים , ניתן להתאמה אישית רבה.

אתה יכול לבנות את האפליקציה עם התקן mvn clean install, ואתה יכול להריץ אותה עם מטרת Spring Boot ( mvn spring-boot:run). לפני שנעשה זאת, בואו נסתכל על pom.xmlקובץ היישום הזה .

רישום 6. Starter pom.xml

 com.javaworld what-is-spring 1.0.0  org.springframework.boot spring-boot-starter-parent 2.1.3.RELEASE     1.8     org.springframework.boot spring-boot-maven-plugin    

שימו לב לשתי תכונות חשובות בקוד שלעיל:

  1. parentהאלמנט מסתמך על spring-boot-starter-parentהפרויקט. פרויקט אב זה מגדיר מספר ברירות מחדל שימושיות, כגון רמת המהדר המוגדרת כברירת מחדל של JDK 1.8. לרוב, אתה יכול פשוט לסמוך שהוא יודע מה הוא עושה. כדוגמה, אתה יכול להשמיט את מספר הגירסה עבור הרבה תלות נפוצה, SpringBootParentותגדיר את הגרסאות להיות תואמות. כאשר אתה מקפיץ את מספר הגרסה של ההורה, גם גרסאות התלות והברירות המחדל ישתנו.
  2. spring-boot-maven-pluginמאפשר JAR הפעלה / WAR האריזה ב-מקום run(דרך mvn spring-boot:runהפקודה).

הוספת רשת האביב כתלות

עד כה הצלחנו להשתמש spring-bootבכדי להגביל כמה עבודה השקענו בכדי להפעיל אפליקציה. עכשיו בואו נוסיף תלות ונראה כמה מהר נוכל להשיג משהו בדפדפן.

רישום 7. הוספת Spring Web לפרויקט

  org.springframework.boot spring-boot-starter-web  

הערה

אביב יאתר אוטומטית אילו קבצים השתנו ויקבץ בהתאם. אתה יכול פשוט לבצע mvn spring-boot:runשינויים באיסוף.

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

דוגמה מס '2: בניית נקודות קצה מנוחות עם Spring Spring

פעם היינו spring-boot-starter-webמביאים כמה תלות שימושיות לבניית יישומי אינטרנט. בשלב הבא ניצור מטפל בנתיב עבור נתיב URL. תמיכת האינטרנט של Spring היא חלק ממודול Spring MVC (Model-View-Controller), אך אל תתנו לזה להדאיג אתכם: ל- Spring Web יש תמיכה מלאה ויעילה גם לבניית נקודות קצה RESTful.

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

רישום 8. בקר MVC REST באביב

 package hello; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RequestParam; @Controller public class GreetingController { @RequestMapping(value = "/hi", method = RequestMethod.GET) public String hi(@RequestParam(name="name", required=false, defaultValue="JavaWorld") String name, Model model) { return "Hello " + name; } } 

ההערה של @Controller

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

הבקר הוא סוג מיוחד של רכיב. הוא תומך @RequestMappingואת @ResponseBodyההסברים שאתה רואה על hi()השיטה. ביאורים אלה מציגים את המסגרת כיצד למפות בקשות URL לאפליקציה.

בשלב זה תוכלו להריץ את האפליקציה באמצעות mvn spring-boot:run. כשתלחץ על /hiכתובת האתר תקבל תגובה כמו "שלום, JavaWorld".

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

ההערות של @Request

זה @RequestMappingמאפשר לך להגדיר מטפל לנתיב URL. האפשרויות כוללות הגדרת שיטת HTTP הרצויה, וזה מה שעשינו במקרה זה. RequestMethodהפסקת פעולה תנחה את התוכנית לטפל בכל סוגי שיטות ה- HTTP.

@RequestParamביאור הטיעון מאפשר לנו למפות את פרמטרי הבקשה ישירות לתוך חתימת השיטה, כולל מחייב פרמטרים מסוימים והגדרת ערכי ברירת מחדל כפי שעשינו כאן. אנו יכולים אפילו למפות גוף בקשה לכיתה עם @RequestBodyהערת הטיעון.

תגובת REST ו- JSON

אם אתה יוצר נקודת קצה של REST וברצונך להחזיר את JSON מהשיטה, אתה יכול להוסיף הערה לשיטה באמצעות @ResponseBody. התגובה תארוז אוטומטית כ- JSON. במקרה זה תחזיר אובייקט מהשיטה.

שימוש ב- MVC עם Spring Web

בדומה ל- Struts, ניתן להשתמש בקלות במודול ה- Spring Web לצורך הגדרת בקר-מודל-מבט אמיתי. במקרה כזה, היית מחזיר מיפוי בשפת התבניות הנתונה (כמו Thymeleaf), ו- Spring היה פותר את המיפוי, מספק את המודל שאתה מעביר אליו ומגיש את התגובה.

דוגמה מס '3: אביב עם JDBC

עכשיו בואו נעשה משהו מעניין יותר עם מטפל הבקשות שלנו: בואו נחזיר כמה נתונים ממסד נתונים. לצורך דוגמה זו נשתמש במסד הנתונים H2. למרבה המזל, Spring Boot תומך ב- H2 DB בזיכרון מהקופסה.