במאמר הקודם
, הסברתי בקצרה מהו אביב ומה זה שעועית והקשר. עכשיו הגיע הזמן לנסות את זה. אני הולך לעשות את זה באמצעות IntelliJ IDEA Enterprise Edition. אבל כל הדוגמאות שלי צריכות לעבוד גם במהדורת הקהילה החינמית של IntelliJ IDEA. בצילומי המסך, אם אתה רואה שיש לי איזה חלון שאין לך, אל תדאג - זה לא חשוב לפרויקט הזה :)
ראשית, צור פרוייקט ריק של Maven. הראיתי איך לעשות זאת במאמר בקישור הזה
. קרא עד המילים " הגיע הזמן שלנו להמיר את פרויקט Maven שלנו לפרויקט אינטרנט. " - לאחר מכן, המאמר מראה כיצד ליצור פרויקט אינטרנט, אבל אנחנו לא צריכים את זה כרגע. בתיקיית src/main/java צור חבילה (במקרה שלי קראתי לזה "
בחלון בצד שמאל, אתה יכול לראות את מבנה הפרויקט עם החבילה והכיתה

en.codegym.info.fatfaggy.animals
. אתה יכול לקרוא לזה איך שאתה רוצה. רק אל תשכח להחליף את שם החבילה שלי בשם החבילה שלך בכל המקומות הנכונים. כעת צור את Main
המחלקה והוסף שיטה
public static void main(String[] args) {
...
}
לאחר מכן, פתח את הקובץ pom.xml והוסף את dependencies
הקטע. כעת עבור אל מאגר Maven
ומצא את ההקשר של Spring עבור הגרסה היציבה האחרונה. הכניסו את מה שאנו מוצאים לסעיף dependencies
. תיארתי את התהליך הזה ביתר פירוט במאמר אחר זה של CodeGym
(ראה את הסעיף שכותרתו " חיבור תלות ב-Maven "). אז Maven עצמה תמצא ותוריד את התלות הדרושות. בסופו של דבר, אתה אמור לקבל משהו כזה: 
Main
. החלון האמצעי מראה איך pom.xml נראה עבורי. הוספתי לו גם סעיף מאפיינים . סעיף זה אומר ל-Maven באיזו גרסה של Java אני משתמש בקבצי המקור שלי ואיזו גרסה להדר. זה רק כדי ש-IDEA לא מזהיר אותי שאני משתמש בגרסה ישנה של Java. זה אופציונלי :) החלון הימני מבהיר שלמרות שחיברנו רק את מודול הקפיץ-קונטקסט, הוא משך אוטומטית את מודולי הקפיץ-ליבת, הקפיץ-שעועית, קפיץ-אופ וקפיץ-ביטוי. יכולנו לחבר כל מודול בנפרד, לכתוב תלות לכל מודול עם הגרסה המפורשת בקובץ pom.xml, אבל לעת עתה אנחנו מרוצים מהמצב כפי שהם. כעת צור את entities
החבילה וצור בה 3 מחלקות: Cat
, Dog
, Parrot
. בוא ניתן לכל חיה שם ( private String name
— אתה יכול לקוד כמה ערכים שם). המגדירים/מקבעים הם ציבוריים. עכשיו אנחנו עוברים לכיתה Main
ולשיטה main()
, ואנחנו כותבים משהו כזה:
public static void main(String[] args) {
// Create an empty Spring context that will look for its own beans based on the annotations in the specified package
ApplicationContext context =
new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.entities");
Cat cat = context.getBean(Cat.class);
Dog dog = (Dog) context.getBean("dog");
Parrot parrot = context.getBean("parrot-polly", Parrot.class);
System.out.println(cat.getName());
System.out.println(dog.getName());
System.out.println(parrot.getName());
}
ראשית, אנו יוצרים אובייקט הקשר, שאומרים לבנאי באיזו חבילה לחפש כדי למצוא שעועית. במילים אחרות, אביב יעבור על החבילה הזו וינסה למצוא שיעורים המסומנים בהערות מיוחדות המעידות על שעועית. לאחר מכן הוא יוצר את האובייקטים של המחלקות הללו ומכניס אותם להקשר. אחרי זה, אנחנו מקבלים חתול מההקשר הזה. אנו קוראים לאובייקט ההקשר לתת לנו שעועית (אובייקט), המציינת את המחלקה של האובייקט שאנו רוצים (אגב, אנו יכולים גם לציין ממשקים, לא רק מחלקות). לאחר מכן, Spring מחזיר אובייקט מהמחלקה המבוקשת, אותו אנו שומרים במשתנה. לאחר מכן, אנו מבקשים מאביב להביא לנו שעועית בשם "כלב". כאשר Spring יוצר Dog
אובייקט, הוא נותן לאובייקט שם סטנדרטי (אלא אם השעועית שנוצרה קיבלה שם במפורש), שהוא שם המחלקה אך עם אות קטנה ראשונית. במקרה זה, הכיתה שלנו נקראת Dog
, אז השם של השעועית הוא להיות "כלב". אם היינו צריכים BufferedReader
אובייקט שם, אז אביב היה קורא לו "bufferedReader". ומכיוון ש-Java לא יכולה להיות בטוחה ב-100% איזו מחלקה אנחנו רוצים, היא מחזירה אובייקט Object
, שלאחר מכן נטיל אותו ידנית לסוג הרצוי, כלומר Dog
. האפשרות שבה המעמד מצוין במפורש נוחה יותר. האפשרות השלישית היא לקבל שעועית לפי שם הכיתה ולפי שם שעועית. ייתכן שההקשר עשוי לכלול כמה שעועית ממחלקה אחת. על מנת לציין את השעועית המסוימת שאנו צריכים, אנו מציינים את שמה. מכיוון שגם כאן אנו מציינים במפורש את המעמד, איננו צריכים עוד לבצע ליהוק. חָשׁוּב!אם אביב מוצא כמה שעועית שתואמות את הדרישות שלנו, אז היא לא יכולה לקבוע איזו שעועית לתת לנו, אז היא תגרום לחריגה. בהתאם לכך, כדי להימנע ממצב זה, כדאי לנסות להיות ספציפיים ככל האפשר לומר לאביב איזו שעועית אתה צריך. אם אביב יחפש את ההקשר שלו ולא יצליח למצוא שעועית אחת שתואמת את הדרישות שלנו, אז היא גם תזרוק חריגה. לבסוף, אנחנו פשוט מציגים את שמות החיות שלנו כדי לוודא שבאמת יש לנו את החפצים שאנחנו צריכים. אבל אם נריץ את התוכנית עכשיו, נראה שאביב לא מרוצה - הוא לא יכול למצוא את החיות שאנחנו צריכים בהקשר שלה. זה בגלל שהוא לא יצר את השעועית האלה. כפי שאמרתי בעבר, כאשר ספרינג סורק שיעורים, הוא מחפש ביאורי אביב משלו. ואם אביב לא מוצא את ההערות האלה, אז הוא לא חושב שהשיעורים האלה מתאימים לשעועית שהוא צריך ליצור. תיקון זה פשוט מצריך הוספת @Component
ההערה לפני כל אחת מכיתות החיות שלנו.
@Component
public class Cat {
private String name = "Oscar";
...
}
אבל יש עוד. אם אנחנו צריכים לומר במפורש ל-Spring שלשעועית למחלקה זו צריך להיות שם ספציפי, נציין את השם בסוגריים אחרי ההערה. לדוגמה, כדי לומר לאביב לתת את השם " parrot-polly
" לשעועית התוכי, שזה השם שבו נשתמש כדי לקבל את התוכי הזה בשיטה main
, עלינו לעשות משהו כזה:
@Component("parrot-polly")
public class Parrot {
private String name = "Polly";
...
}
זו כל הנקודה של תצורה אוטומטית . אתה כותב את השיעורים שלך, מסמן אותם בהערות הנחוצות, ומספר לאביב את החבילה הכוללת את השיעורים שלך. זו החבילה שהמסגרת תעבור דרכה כדי למצוא הערות וליצור אובייקטים של מחלקות אלה. אגב, ספרינג לא מחפש רק @Component
הערות, אלא גם את כל ההערות האחרות שיורשים את זה. לדוגמה, @Controller
, @RestController
, @Service
, @Repository
ועוד, אותם נציג במאמרים הבאים. כעת ננסה לעשות את אותו הדבר באמצעות תצורה מבוססת Java . כדי להתחיל, הסר את @Component
ההערות מהשיעורים שלנו. כדי להפוך את הדברים למאתגרים יותר, דמיינו שלא כתבנו את השיעורים האלה, כך שלא נוכל לשנות אותם בקלות, מה שאומר שאיננו יכולים להוסיף הערות. זה כאילו השיעורים האלה ארוזים באיזו ספרייה. במקרה זה, אין לנו דרך לערוך את המחלקות הללו כך שיזוהו על ידי Spring. אבל אנחנו צריכים אובייקטים של המעמדות האלה! כאן אנחנו צריכים תצורה מבוססת Java כדי ליצור את האובייקטים. כדי להתחיל, צור חבילה בשם כמו configs
. בחבילה זו, צור מחלקה רגילה של Java, משהו כמו MyConfig
, וסמן אותה עם @Configuration
ההערה.
@Configuration
public class MyConfig {
}
עכשיו אנחנו צריכים לשנות את main()
השיטה, לשנות את האופן שבו אנחנו יוצרים את ההקשר. אנחנו יכולים לציין במפורש לאיזו מחלקה יש את התצורה שלנו:
ApplicationContext context =
new AnnotationConfigApplicationContext(MyConfig.class);
אם יש לנו כמה מחלקות שונות שיוצרות שעועית ואנו רוצים לחבר כמה מהן בו זמנית, אנחנו פשוט מציינים את כולם שם, מופרדים בפסיקים:
ApplicationContext context =
new AnnotationConfigApplicationContext(MyConfig.class, MyAnotherConfig.class);
ואם יש לנו יותר מדי מהם ואנחנו רוצים לחבר את כולם בו זמנית, אז אנחנו פשוט מציינים את שם החבילה שהם כלולים בה:
ApplicationContext context =
new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.configs");
במקרה זה, אביב יעבור על החבילה וימצא את כל השיעורים המסומנים בהערה @Configuration
. ובכן, ואם יש לנו תוכנית ממש גדולה שבה התצורות מחולקות לחבילות שונות, אז אנחנו פשוט מציינים רשימה מופרדת בפסיקים של שמות החבילות שמכילות את התצורות:
ApplicationContext context =
new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.database.configs",
"en.codegym.info.fatfaggy.animals.root.configs",
"en.codegym.info.fatfaggy.animals.web.configs");
או שם של חבילה שמשותף לכולם:
ApplicationContext context =
new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals");
אתה יכול לעשות את זה איך שאתה רוצה, אבל נראה לי שהאפשרות הראשונה, שפשוט מציינת מחלקה עם הקונפיגורציות, תתאים ביותר לתוכנית שלנו. בעת יצירת הקשר, Spring מחפש מחלקות המסומנות בהערה @Configuration
וייצור אובייקטים משלו של מחלקות אלו. הוא מנסה לקרוא לשיטות המסומנות עם @Bean
ההערה, מה שאומר ששיטות אלו מחזירות שעועית (אובייקטים) ש-Spring יוסיף להקשר. ועכשיו ניצור שעועית עבור חתול, כלב ותוכי בכיתה שלנו עם תצורה מבוססת Java. זה די פשוט לביצוע:
@Bean
public Cat getCat() {
return new Cat();
}
כאן אנו יוצרים ידנית את החתול שלנו ומעבירים אותו לאביב, אשר לאחר מכן מחזיק את החפץ שלנו בהקשר שלו. מכיוון שלא נתנו שם במפורש לשעועית שלנו, אביב ייתן לה את אותו שם כמו שם השיטה. במקרה שלנו, שעועית החתול תיקרא " getCat
". אבל בגלל שאנחנו משתמשים בכיתה, לא בשם, כדי לקבל את שעועית החתול בשיטה main
, השם של השעועית לא חשוב לנו. באופן דומה, צור שעועית לכלב, תוך התחשבות שאביב ייתן את שם השיטה לשעועית. כדי לתת שם מפורש לשעועית התוכי שלנו, אנו פשוט מציינים את שמה בסוגריים אחרי @Bean
ההערה:
@Bean("parrot-polly")
public Object weNeedMoreParrots() {
return new Parrot();
}
כפי שניתן לראות, כאן ציינתי Object
סוג החזרה ונתתי לשיטה שם שרירותי. זה לא משפיע על שם השעועית, מכיוון שציינו כאן במפורש את השם. ובכל זאת, עדיף לציין ערך החזרה ושם שיטה משמעותיים יותר או פחות. עשה זאת אם אין סיבה אחרת מלבד לעשות לעצמך טובה כשאתה פותח מחדש את הפרויקט בעוד שנה. :) עכשיו שקול את המצב שבו אנחנו צריכים שעועית אחת כדי ליצור שעועית אחרת . לדוגמה, נניח שאנו רוצים ששם החתול בשעועית החתול יהיה שם התוכי בתוספת המחרוזת "-רוצח". אין בעיה!
@Bean
public Cat getCat(Parrot parrot) {
Cat cat = new Cat();
cat.setName(parrot.getName() + "-killer");
return cat;
}
כאן אביב יראה שכדי ליצור את השעועית הזו, המסגרת צריכה לעבור בשעועית התוכי שנוצרה בעבר. בהתאם, הוא יסדר את שרשרת הקריאות המתודה הנדרשת: ראשית, נקראת השיטה ליצירת תוכי ולאחר מכן המסגרת מעבירה את התוכי החדש לשיטת יצירת החתול. כאן נכנסת לתמונה הזרקת תלות : האביב עצמו מעביר את שעועית התוכי הנדרשת לשיטה שלנו. אם IDEA מתעצבן על parrot
המשתנה, אל תשכח לשנות את סוג ההחזרה של שיטת יצירת התוכים מ- Object
ל Parrot
. בנוסף, תצורה מבוססת Java מאפשרת לך להריץ כל קוד Java בשיטות יצירת השעועית שלך. אתה באמת יכול לעשות הכל: ליצור אובייקטים עזר אחרים, לקרוא לכל שיטות אחרות, אפילו אלה שאינן מסומנות עם הערות Spring, ליצור לולאות, תנאים בוליאניים - מה שעולה על דעתך! לא הכל אפשרי עם תצורה אוטומטית, ועוד פחות מכך עם תצורת XML. עכשיו בואו נשקול בעיה שהיא קצת יותר מהנה. פולימורפיזם וממשקים :) ניצור WeekDay
ממשק וניצור 7 מחלקות שמיישמות את הממשק הזה: Monday
, Tuesday
, Wednesday
, Thursday
, Friday
, Saturday
, Sunday
. ניתן לממשק שיטה String getWeekDayName()
, שתחזיר את שם היום בשבוע עבור הכיתה המקבילה. במילים אחרות, Monday
הכיתה תחזיר " Monday
" וכו'. עם תחילת היישום, נניח שהמשימה שלנו היא להכניס שעועית המתאימה ליום הנוכחי בשבוע בהקשר. לא שעועית לכל המחלקות שמיישמות את WeekDay
הממשק - רק השעועית האחת שאנחנו צריכים. אתה יכול לעשות את זה בערך ככה:
@Bean
public WeekDay getDay() {
DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
switch (dayOfWeek) {
case MONDAY: return new Monday();
case TUESDAY: return new Tuesday();
case WEDNESDAY: return new Wednesday();
case THURSDAY: return new Thursday();
case FRIDAY: return new Friday();
case SATURDAY: return new Saturday();
default: return new Sunday();
}
}
כאן סוג ההחזרה הוא הממשק שלנו. השיטה מחזירה אובייקט בתום לב של אחת המחלקות שמיישמות את הממשק, בהתאם ליום הנוכחי בשבוע. כעת נוכל לעשות את הדברים הבאים בשיטה main()
:
WeekDay weekDay = context.getBean(WeekDay.class);
System.out.println("Today is " + weekDay.getWeekDayName() + "!");
מבחינתי, התוכנית אומרת לי שזה יום ראשון :) אני בטוח שאם אפעיל את התוכנית מחר, ההקשר יכיל אובייקט אחר לגמרי. שים לב שאנו מקבלים את השעועית פשוט באמצעות הממשק: context.getBean(WeekDay.class)
. Spring יחפש את ההקשר שלו אחר השעועית המיישמת את הממשק, ויחזיר אותו. ואז מסתבר שהמשתנה שלנו WeekDay
מסתיים באובייקט של יום ראשון, והמושג המוכר של פולימורפיזם חל כשאנחנו עובדים עם המשתנה הזה. :) עכשיו כמה מילים על הגישה המשולבת , שבה חלק מהשעועית נוצרת אוטומטית על ידי Spring, חלק על ידי סריקת חבילות למחלקות עם ההערה @Component
, ואחרות על ידי תצורה מבוססת Java. כאשר אנו שוקלים זאת, נחזור לגרסה המקורית, שבה סומנו ה- Cat
, Dog
, והשיעורים Parrot
עם @Component
ההערה. נניח שאנחנו רוצים ליצור שעועית לבעלי החיים שלנו על ידי כך שאביב יסרוק אוטומטית את entities
החבילה, אבל אנחנו גם רוצים ליצור שעועית עם היום בשבוע, כמו שעשינו זה עתה. כל מה שצריך לעשות הוא להוסיף את @ComponentScan
ההערה ברמת המחלקה MyConfig
, אותה אנו מציינים בעת יצירת ההקשר ב- main()
, ולציין בסוגריים את החבילה שצריך לסרוק וליצור שעועית של המחלקות הנחוצות באופן אוטומטי:
@Configuration
@ComponentScan("en.codegym.info.fatfaggy.animals.entities")
public class MyConfig {
@Bean
public WeekDay getDay() {
DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
switch (dayOfWeek) {
case MONDAY: return new Monday();
case TUESDAY: return new Tuesday();
case WEDNESDAY: return new Wednesday();
case THURSDAY: return new Thursday();
case FRIDAY: return new Friday();
case SATURDAY: return new Saturday();
default: return new Sunday();
}
}
}
כשיוצרים את ההקשר, אביב רואה שהוא צריך לעבד את MyConfig
הכיתה. הוא נכנס למחלקה ורואה שהוא צריך לסרוק את en.codegym.info.fatfaggy.animals.entities
החבילה " " וליצור שעועית של המחלקות הללו, ולאחר מכן הוא מבצע את השיטה MyConfig
של המחלקה getDay()
ומוסיף WeekDay
שעועית להקשר. בשיטה main()
יש לנו עכשיו גישה לכל השעועית שאנחנו צריכים: גם חפצים של בעלי חיים וגם שעועית עם היום בשבוע. אם אי פעם תצטרך לגרום ל-Spring גם לאסוף כמה קובצי תצורה של XML, אתה יכול לעשות חיפוש אינטרנט משלך כדי למצוא הסבר :) סיכום:
- נסה להשתמש בתצורה אוטומטית
- במהלך התצורה האוטומטית, ציין את שם החבילה המכילה את המחלקות שיש ליצור את הפולים שלהן
- שיעורים אלה מסומנים עם
@Component
ההערה - אביב עובר דרך כל המחלקות הללו, יוצר אובייקטים ומכניס אותם להקשר;
- אם תצורה אוטומטית לא מתאימה לנו מסיבה כלשהי, אנו משתמשים בתצורה מבוססת Java
- במקרה זה, אנו יוצרים מחלקת Java רגילה שהשיטות שלה מחזירות את האובייקטים שאנו צריכים. אנו מסמנים את המחלקה הזו עם
@Configuration
ההערה אם אנחנו מתכוונים לסרוק את כל החבילה במקום לציין מחלקה ספציפית עם התצורה בעת יצירת ההקשר - השיטות של מחלקה זו המחזירות שעועית מסומנות עם
@Bean
ההערה
@ComponentScan
.
GO TO FULL VERSION