JavaRush /בלוג Java /Random-HE /האביב מיועד לעצלנים. יסודות, מושגי יסוד ודוגמאות עם קוד. ...
Стас Пасинков
רָמָה
Киев

האביב מיועד לעצלנים. יסודות, מושגי יסוד ודוגמאות עם קוד. חלק 2

פורסם בקבוצה
במאמר האחרון , הסברתי בקצרה מהו אביב, מה זה פחים והקשר. עכשיו הגיע הזמן לנסות איך הכל עובד. האביב מיועד לעצלנים.  יסודות, מושגי יסוד ודוגמאות עם קוד.  חלק 2 - 1אני אעשה זאת בעצמי ב- Intellij Idea Enterprise Edition. אבל כל הדוגמאות שלי צריכות לעבוד גם במהדורת הקהילה החינמית של Intellij Idea. רק אם אתם רואים בצילומי המסך שיש לי איזשהו חלון שאין לכם, אל דאגה, זה לא קריטי לפרויקט הזה :) ראשית, בואו ניצור פרויקט Maven ריק. הראיתי איך עושים זאת במאמר (קראו עד המילים " הגיע הזמן להפוך את פרויקט ה-maven שלנו לפרויקט אינטרנט. ", אחרי זה הוא כבר מראה איך ליצור פרויקט אינטרנט, ואנחנו לא צריכים את זה עכשיו) בוא ניצור אותו בתיקייה src/main /java היא חבילה כלשהי (במקרה שלי קראתי לזה " ru.javarush.info.fatfaggy.animals", אתה יכול לקרוא לזה איך שאתה רוצה, רק אל תשכח להחליף אותו בשמך במקומות הנכונים). ובואו ניצור מחלקה Mainבה נכין שיטה
public static void main(String[] args) {
    ...
}
לאחר מכן פתח את הקובץ pom.xml והוסף שם קטע dependencies. עכשיו אנחנו הולכים למאגר Maven ומחפשים את ההקשר האביבי של הגרסה היציבה האחרונה שם, ומדביקים את מה שקיבלנו בתוך המדור dependencies. תיארתי את התהליך הזה בפירוט קטן יותר במאמר זה (ראה את הסעיף " חיבור תלות ב-Maven "). אז Maven עצמו ימצא ותוריד את התלות הדרושות, ובסופו של דבר אתה אמור לקבל משהו כזה:
האביב מיועד לעצלנים.  יסודות, מושגי יסוד ודוגמאות עם קוד.  חלק 2 - 2
בחלון השמאלי ניתן לראות את מבנה הפרויקט עם החבילה והכיתה Main. החלון האמצעי מראה איך ה-pom.xml שלי נראה. הוספתי שם גם סעיף מאפיינים , שבו ציינתי ל-Maven באיזו גרסה של Java אני משתמש בקוד המקור ובאיזה גרסה להדר. זה רק כדי שלא אקבל את הרעיון של אזהרה בעת ההפעלה כי נעשה שימוש בגרסה ישנה של Java. אתה יכול לעשות את זה, אתה לא יכול) בחלון הימני - אתה יכול לראות שלמרות שחיברנו רק את ההקשר האביבי - זה הוסיף אוטומטית ליבה, שעועית, aop וביטוי. ניתן היה לחבר כל מודול בנפרד, תוך רישום תלות עבור כל אחד מהם בזיכרון עם ציון מפורש של הגרסה, אך לעת עתה אנו מרוצים מהאופציה כפי שהיא כעת. כעת ניצור חבילה entities(ישויות) וניצור בה 3 מחלקות: Cat, Dog, Parrot. תן לכל חיה להיות שם ( private String name, אתה יכול לקוד קשיח כמה ערכים שם), והמקבלים/מגדירים הם ציבוריים. עכשיו לך לכיתה Mainוכתוב main()משהו כזה בשיטה:
public static void main(String[] args) {
	// create an empty spring context that will search for its beans by annotations in the specified package
	ApplicationContext context =
		new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals.entities");

	Cat cat = context.getBean(Cat.class);
	Dog dog = (Dog) context.getBean("dog");
	Parrot parrot = context.getBean("parrot-kesha", Parrot.class);

	System.out.println(cat.getName());
	System.out.println(dog.getName());
	System.out.println(parrot.getName());
}
ראשית, אנו יוצרים אובייקט קונטקסט, ובקונסטרוקטור אנו נותנים לו את שם החבילה שצריך לסרוק עבור נוכחות שעועית. כלומר, ספרינג יעבור על החבילה הזו וינסה למצוא שיעורים המסומנים בביאורים מיוחדים שמודיעים לאביב שמדובר בשעועית. לאחר מכן הוא יוצר אובייקטים של מחלקות אלו וממקם אותם בהקשר שלו. לאחר מכן אנו מקבלים חתול מההקשר הזה. כשפונים לאובייקט ההקשר, אנחנו מבקשים ממנו לתת לנו שעועית (אובייקט), ולציין איזה מחלקה של אובייקט אנחנו צריכים (כאן, אגב, אפשר לציין לא רק מחלקות, אלא גם ממשקים). לאחר מכן Spring מחזיר לנו אובייקט מהמחלקה הזו, אותו אנו שומרים למשתנה. לאחר מכן, אנו מבקשים מאביב להביא לנו שעועית בשם "כלב". כאשר Spring יוצר אובייקט מחלקה, Dogהוא ייתן לו שם סטנדרטי (אם שם השעועית שנוצרת לא מצוין במפורש), שהוא שם המחלקה של האובייקט, רק עם אות קטנה. לכן, מכיוון שהכיתה שלנו נקראת Dog, השם של שעועית כזו יהיה "כלב". אם היה לנו שם אובייקט BufferedReader, אז Spring היה נותן לו את שם ברירת המחדל "bufferedReader". ומכיוון שבמקרה זה (ב-Java) אין ודאות מדויקת לאיזה מחלקה יהיה אובייקט כזה, אז פשוט מוחזר אחד מסוים Object, שאותו אנו משליכים ידנית לסוג שאנו צריכים Dog. האפשרות עם ציון מפורש של המחלקה נוחה יותר. ובכן, במקרה השלישי, אנחנו מקבלים שעועית לפי הכיתה והשם. יכול להיות פשוט מצב שבו בהקשר יהיו כמה שעועית של מחלקה אחת, וכדי לציין איזו שעועית מסוימת אנחנו צריכים, נציין את השם שלה. מכיוון שגם כאן ציינו בבירור את המעמד, כבר לא צריך ללהק. חָשׁוּב!אם יתברר שאביב ימצא מספר פולים לפי הדרישות שציינו לו, הוא לא יוכל לקבוע איזו שעועית לתת לנו ותזרוק חריגה. לכן, נסו לציין בפניו בצורה מדויקת ככל האפשר איזה פח אתם צריכים, כדי שלא ייווצרו מצבים כאלה. אם אביב לא ימצא שעועית אחת בהקשר שלה לפי התנאים שלך, הוא גם יזרוק חריג. ובכן, אז אנחנו פשוט מציגים את שמות החיות שלנו על המסך כדי לוודא שאלו הם בעצם בדיוק החפצים שאנחנו צריכים. אבל אם נריץ את התוכנית עכשיו, נראה שאביב נשבע שהוא לא יכול למצוא את החיות שאנחנו צריכים בהקשר שלה. זה קרה בגלל שהוא לא יצר את השעועית האלה. כפי שכבר אמרתי, כשאביב סורק שיעורים, הוא מחפש שם את הערות האביב "שלו". ואם זה לא מוצא את זה, אז זה לא תופס כיתות כאלה ככאלו שהוא צריך ליצור את השעועית שלהם. כדי לתקן זאת, פשוט הוסף הערה @Componentלפני הכיתה בכיתות החיות שלנו.
@Component
public class Cat {
	private String name = "Barsik";
	...
}
אבל זה לא הכל. אם אנחנו צריכים לציין במפורש ל-Spring שלשעועית למחלקה זו צריך להיות שם ספציפי, ניתן לציין שם זה בסוגריים אחרי ההערה. למשל, כדי שאביב ייתן את השם שאנחנו צריכים parrot-keshaלשעועית התוכי, שממנה mainנקבל אחר כך את התוכי הזה, אנחנו צריכים לעשות משהו כזה:
@Component("parrot-kesha")
public class Parrot {
	private String name = "Kesha";
	...
}
זו כל הנקודה של תצורה אוטומטית . אתם כותבים את השיעורים שלכם, מסמנים אותם בהערות הנדרשות ומציינים ל-Spring חבילה עם הכיתות שלכם, שדרכה הוא עובר, מחפש ביאורים ויוצר אובייקטים של כיתות כאלה. אגב, אביב יחפש לא רק בהערות @Component, אלא גם בכל ההערות האחרות שעברו בירושה מהערה זו. לדוגמה, @Controller, @RestController, @Serviceואחרים @Repository, אותם נפגוש במאמרים נוספים. עכשיו בואו ננסה לעשות את אותו הדבר, אבל באמצעות תצורת java . ראשית, בואו נסיר הערות @Componentמהשיעורים שלנו. כדי לסבך את המשימה, בואו נדמיין שאלו לא שיעורים שנכתבו בעצמנו, אותם אנחנו יכולים בקלות לשנות, להוסיף משהו, כולל הערות. זה כאילו השיעורים האלה ארוזים באיזו ספרייה. במקרה זה, איננו יכולים לערוך את המחלקות הללו בשום אופן כך שיתקבלו עד האביב. אבל אנחנו צריכים אובייקטים של המעמדות האלה! כאן נצטרך את תצורת ה-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("ru.javarush.info.fatfaggy.animals.configs");
במקרה זה, אביב יעבור על החבילה הזו וימצא את כל השיעורים המסומנים בהערה @Configuration. ובכן, במקרה שיש לנו תוכנית ממש גדולה שבה התצורות מחולקות לחבילות שונות, אנו פשוט מציינים את שמות החבילות עם תצורות מופרדות בפסיקים:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals.database.configs",
		"ru.javarush.info.fatfaggy.animals.root.configs",
		"ru.javarush.info.fatfaggy.animals.web.configs");
ובכן, או שם החבילה הנפוצה יותר לכולן:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals");
אתה יכול לעשות את זה כרצונך, אבל נראה לי שהאפשרות הראשונה, שבה אתה פשוט מציין מחלקה עם הגדרות, תתאים ביותר לתוכנית שלנו. בעת יצירת הקשר, Spring יחפש את המחלקות המסומנות עם ההערה @Configurationויצור אובייקטים של מחלקות אלו בעצמו. לאחר מכן היא תנסה לקרוא למתודות במחלקות הללו המסומנות עם ההערה @Bean, מה שאומר ששיטות כאלו יחזירו שעועית (אובייקטים) שהיא כבר הציב בהקשר שלה. ובכן, עכשיו בואו ניצור שעועית חתול, כלב ותוכים בכיתה שלנו עם תצורת ג'אווה. זה נעשה בפשטות:
@Bean
public Cat getCat() {
	return new Cat();
}
מסתבר שיצרנו בעצמנו את החתול שלנו באופן ידני ונתנו אותו לאביב, והוא כבר הציב את החפץ הזה שלנו בהקשר שלו. מכיוון שלא ציינו במפורש את שם השעועית שלנו, ספרינג ייתן לשעועית את השם הזהה לשם השיטה. במקרה שלנו, לשעועית של החתול יהיה השם " getCat". אבל מכיוון שב- maine אנחנו עדיין מקבלים את החתול לא לפי השם, אלא לפי הכיתה, אז במקרה הזה השם של הפח הזה לא חשוב לנו. הכינו שעועית עם כלב באותו אופן, אבל קחו בחשבון שאביב יקרא לשעועית כזו בשם השיטה. כדי לתת שם מפורש לשעועית שלנו עם התוכי, פשוט ציין את שמה בסוגריים אחרי ההערה @Bean:
@Bean("parrot-kesha")
public Object weNeedMoreParrots() {
	return new Parrot();
}
כפי שאתה יכול לראות, כאן ציינתי את סוג ערך ההחזרה Object, וקראתי לשיטה משהו בכלל. זה לא משפיע על שם השעועית בשום צורה כי הגדרנו אותו כאן במפורש. אבל עדיף לציין את סוג ערך ההחזרה ואת שם השיטה לא על הסף, אלא פחות או יותר ברור. רק בשביל עצמך, כשאתה פותח את הפרויקט הזה בעוד שנה. :) עכשיו בואו נשקול מצב שבו כדי ליצור שעועית אחת אנחנו צריכים להשתמש בשעועית אחרת . לדוגמה, אנו רוצים ששם החתול בשעועית החתול יהיה מורכב משמו של התוכי ומהמחרוזת "-רוצח". אין בעיה!
@Bean
public Cat getCat(Parrot parrot) {
	Cat cat = new Cat();
	cat.setName(parrot.getName() + "-killer");
	return cat;
}
כאן אביב יראה שלפני יצירת שעועית זו, הוא יצטרך להעביר לכאן את שעועית התוכי שכבר נוצרה. לכן הוא יבנה שרשרת קריאות לשיטות שלנו כך שקודם תקרא השיטה ליצירת תוכי, ולאחר מכן יעביר את התוכי הזה לשיטת יצירת החתול. כאן עבד הדבר שנקרא הזרקת תלות : האביב עצמו העביר את שעועית התוכי הנדרשת לשיטה שלנו. אם הרעיון מתלונן על משתנה parrot, אל תשכח לשנות את סוג ההחזרה בשיטה ליצירת תוכי מ- Objectל Parrot. בנוסף, תצורת Java מאפשרת לך לבצע לחלוטין כל קוד Java בשיטות ליצירת שעועית. אתה באמת יכול לעשות הכל: ליצור חפצי עזר אחרים, לקרוא לכל שיטות אחרות, גם לאלו שאינן מסומנות בהערות קפיץ, ליצור לולאות, תנאים - מה שעולה על דעתך! לא ניתן להשיג את כל זה באמצעות תצורה אוטומטית, הרבה פחות באמצעות תצורות 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("It's " + weekDay.getWeekDayName() + " today!");
זה אמר לי שהיום יום ראשון :) אני בטוח שאם אני אפעיל את התוכנית מחר, יופיע בהקשר אובייקט אחר לגמרי. שימו לב שכאן אנו מקבלים את השעועית פשוט על ידי הממשק: context.getBean(WeekDay.class). אביב יחפש בהקשר שלו מי מהשעועית שלו מיישם ממשק כזה ויחזיר אותו. ובכן, אז מסתבר שיש WeekDayאובייקט מסוג במשתנה מסוג Sunday, ופולימורפיזם, שכבר מוכר לכולנו, מתחיל בעבודה עם המשתנה הזה. :) וכמה מילים על הגישה המשולבת , שבה חלק מהשעועית נוצרת על ידי Spring עצמה, באמצעות סריקה של חבילות עבור נוכחות של מחלקות עם הערה @Component, ועוד כמה שעועית נוצרת באמצעות תצורת java. כדי לעשות זאת, הבה נחזור לגרסה המקורית, כאשר השיעורים Cat, Dogוסומנו Parrotבהערה @Component. נניח שאנו רוצים ליצור פחים לבעלי החיים שלנו באמצעות סריקה אוטומטית של האריזה entitiesעד האביב, אבל ליצור פח עם היום בשבוע כפי שעשינו זה עתה. כל שעליכם לעשות הוא להוסיף ברמת המחלקה MyConfig, אותה אנו מציינים בעת יצירת ההקשר בהערה main@ComponentScan, ולציין בסוגריים את החבילה שיש לסרוק ואת השעועית של המחלקות הנחוצות ליצור באופן אוטומטי:
@Configuration
@ComponentScan("ru.javarush.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. הוא נכנס לזה ורואה שהוא צריך לסרוק את החבילה " ru.javarush.info.fatfaggy.animals.entities" וליצור שעועית של אותם מחלקות, ולאחר מכן הוא מבצע שיטה getDay()מהמחלקה MyConfigומוסיף שעועית מהסוג WeekDayלהקשר שלו. בשיטה main()יש לנו כעת גישה לכל השעועית שאנו צריכים: גם חפצי החי וגם שעועית היום בשבוע. איך לוודא ש-Spring גם קולט כמה הגדרות xml - חפש בגוגל באינטרנט בעצמך אם אתה צריך את זה :) סיכום:
  • נסה להשתמש בתצורה אוטומטית;
  • במהלך התצורה האוטומטית, אנו מציינים את שם החבילה המכילה את המחלקות שיש ליצור את הפולים שלהן;
  • שיעורים כאלה מסומנים בהערה@Component;
  • האביב עובר דרך כל המעמדות הללו ויוצר את האובייקטים שלהם וממקם אותם בהקשר;
  • אם תצורה אוטומטית לא מתאימה לנו מסיבה כלשהי, אנו משתמשים בתצורת java;
  • במקרה זה, אנו יוצרים מחלקת Java רגילה, שהשיטות שלה יחזירו את האובייקטים הדרושים לנו, וסמנו מחלקה כזו עם הערה @Configurationלמקרה שנסרוק את כל החבילה במקום לציין מחלקה ספציפית עם תצורה בעת יצירת ההקשר;
  • שיטות של מחלקה זו המחזירות שעועית מסומנות עם ההערה @Bean;
  • אם ברצוננו לאפשר סריקה אוטומטית בעת שימוש בתצורת java, אנו משתמשים בהערה @ComponentScan.
אם שום דבר לא ברור, נסה לקרוא את המאמר הזה בעוד כמה ימים. ובכן, או אם אתה ברמות המוקדמות של Javarash, אז אולי זה קצת מוקדם בשבילך ללמוד את האביב. אתה תמיד יכול לחזור למאמר זה קצת מאוחר יותר, כאשר אתה מרגיש בטוח יותר בתכנות ב-Java. אם הכל ברור, אתה יכול לנסות להעביר חלק מהפרויקטים של חיית המחמד שלך לאביב :) אם משהו ברור, אבל משהו לא כל כך, בבקשה תגיב :) יש גם הצעות והערות אם דרכתי לאנשהו או כתבתי משהו טיפשי ) במאמר הבא נצלול עמוק לתוך spring-web-mvc וניצור יישום אינטרנט פשוט באמצעות spring.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION