JavaRush /בלוג Java /Random-HE /אביב. שיעור 2. IoC/DI בפועל
Umaralikhon
רָמָה
Красноярск

אביב. שיעור 2. IoC/DI בפועל

פורסם בקבוצה
וכך... בשיעור הקודם סקרנו בקצרה את החלק התיאורטי של IoC ו-DI. הגדרנו גם את קובץ התצורה pom.xml עבור הפרויקט שלנו. היום אנחנו מתחילים ליצור את החלק העיקרי של התוכנית. ראשית, אני אראה לך כיצד ליצור תוכנית ללא IoC / DI. ואז ניצור ישירות תוכנית שמציגה תלות באופן עצמאי. כלומר, השליטה בקוד עוברת לידי המסגרת (נשמע קריפי). בזמן שאנחנו מנהלים את התוכנית, דמיינו שיש חברה מסוימת. ולחברה (בינתיים) יש שתי מחלקות: Java Development and Hiring Department. תן לכיתה המתארת ​​את "מחלקת הפיתוח של Java" שתי שיטות: String getName() - החזרת שם העובד, String getJob() - החזרת עמדת העובד. (רישום 1)
package org.example;

public class JavaDevelopment {

    public String getName(){
        return "Alexa";
    }

    public String getJob(){
        return "Middle Java developer";
    }
}
תן לכיתה המתארת ​​את מחלקת הגיוס יש בנאי קלט שמקבל עובד, ושיטה void displayInfo() שמציגה מידע על עובדים. (רישום 2)
package org.example;

public class HiringDepartment {
    private JavaDevelopment javaDevelopment;

    public HiringDepartment(JavaDevelopment javaDevelopment) {
        this.javaDevelopment = javaDevelopment;
    }

    public void displayInfo() {
        System.out.println("Name: " + javaDevelopment.getName());
        System.out.println("Job: " + javaDevelopment.getJob());
    }
}
יש גם Main - כיתה שמנהלת את כל המחלקות. (רישום 3)
package org.example;

public class Main {
    public static void main(String ... args){
        JavaDevelopment javaDevelopment = new JavaDevelopment();
        HiringDepartment hiringDepartment = new HiringDepartment(javaDevelopment);

        hiringDepartment.displayInfo();
    }
}
יציבות לעת עתה. כאשר אנו מריצים את ה-Main class אנו מקבלים את התוצאה הבאה:
Name: Alexa
Job: Middle Java developer
עכשיו בואו נדמיין שהחברה פועלת מצוין. לכן, הם החליטו להרחיב את היקף פעילותם ופתחו מחלקת פיתוח של Python. וכאן נשאלת השאלה: איך לתאר את המחלקה הזו ברמת התכנית? תשובה: אתה צריך "להעתיק ולהדביק" בכל מקום שאתה צריך כדי לתאר את המחלקה הזו (השיטה הישנה והטובה🙃). ראשית, בואו ניצור את המחלקה עצמה, שתתאר את מחלקת ה"פיתוניסטים". (רישום 4)
package org.example;

public class PythonDevelopment {
    public String getName(){
        return "Mike";
    }

    public String getJob(){
        return "Middle Python developer";
    }
}
ואז נעביר את זה למחלקת הגיוס. ומחלקת ההעסקה לא אומרת כלום על המחלקה הזו. לכן, תצטרך ליצור אובייקט חדש של המחלקה PythonDevelopment ובנאי שמקבל מפתחי Python. תצטרך גם לשנות את שיטת displayInfo() כך שהיא תציג מידע בצורה נכונה. (רשימה 5)
package org.example;

public class HiringDepartment {
    private JavaDevelopment javaDevelopment;

    public HiringDepartment(JavaDevelopment javaDevelopment) {
        this.javaDevelopment = javaDevelopment;
    }


    //Тут создается отдел найма для Python - разработчиков
    private PythonDevelopment pythonDevelopment;

    public HiringDepartment(PythonDevelopment pythonDevelopment) {
        this.pythonDevelopment = pythonDevelopment;
    }

    //Тогда придется изменить метод displayInfo()
    public void displayInfo() {
        if(javaDevelopment != null) {
            System.out.println("Name: " + javaDevelopment.getName());
            System.out.println("Job: " + javaDevelopment.getJob());
        } else if (pythonDevelopment != null){
            System.out.println("Name: " + pythonDevelopment.getName());
            System.out.println("Job: " + pythonDevelopment.getJob());
        }
    }
}
כפי שאנו יכולים לראות, נפח הקוד הוכפל, או אפילו יותר. עם כמות גדולה של קוד, הקריאות שלו יורדת. והדבר הגרוע ביותר הוא שאנו יוצרים את כל האובייקטים באופן ידני ויוצרים מחלקות שתלויות מאוד אחת בשניה. אוקיי, הסכמנו עם זה. הם רק תיארו מחלקה אחת. לא נפסיד מזה כלום. ובכן, מה אם נוסיף עוד מחלקה? מה אם יש שניים? שְׁלוֹשָׁה? אבל אף אחד לא אסר על "כרייה ומרעה". אביב.  שיעור 2. IoC / DI בפועל - 1 כן, אף אחד לא אסר על "מכרה ומרעה", אבל זה לא מקצועי. Tyzh הוא מתכנת. וכאן אתה יכול להשתמש ב-DI. כלומר, לא נעבוד ברמת הכיתה, אלא ברמת הממשק. כעת המצבים של האובייקטים שלנו יאוחסנו בממשקים. בדרך זו, התלות בין השיעורים תהיה מינימלית. לשם כך, אנו יוצרים תחילה את ממשק הפיתוח, בו יש שתי שיטות לתיאור עובד. (רישום 6)
package org.example;

public interface Development {
    String getName();
    String getJob();
}
לאחר מכן, תנו לשתי מחלקות JavaDevelopment ו-PythonDevelopment ליישם (בירושה) מהממשק הזה ולעקוף את המתודות String getName() ו-String getJob(). (רישום 7, 8)
package org.example;

public class JavaDevelopment implements Development {
    @Override
    public String getName(){
        return "Alexa";
    }

    @Override
    public String getJob(){
        return "Middle Java developer";
    }
}
package org.example;

public class PythonDevelopment implements Development {
    @Override
    public String getName(){
        return "Mike";
    }

    @Override
    public String getJob(){
        return "Middle Python developer";
    }
}
לאחר מכן במחלקה של HiringDepartment אתה יכול פשוט להגדיר אובייקט ממשק מסוג Development ואפשר גם להעביר אובייקט כזה לבנאי. (רישום 9)
package org.example;

public class HiringDepartment {
    private Development development; //Определяем интерфейс

    //Конструктор принимает an object интерфейса
    public HiringDepartment(Development development){
        this.development = development;
    }

    public void displayInfo(){
        System.out.println("Name: " + development.getName());
        System.out.println("Job: " + development.getJob());
    }
}
כפי שאנו יכולים לראות, כמות הקוד ירדה. והכי חשוב, התלות צומצמה. כיצד מיושמים בפועל ערכים ותלות עבור אובייקטים אלו? ישנן שלוש דרכים לבצע הזרקת תלות:
  • שימוש בקונסטרוקטור
  • שימוש בהגדרות
  • חיווט אוטומטי (כריכה אוטומטית)
יישום באמצעות בנאי עכשיו בואו נדבר על יישום באמצעות בנאי. תסתכל על רישום 9. הבנאי של המחלקה HiringDepartment מצפה לאובייקט מסוג Development כקלט. ננסה להחדיר תלות דרך בנאי זה. ראוי גם לציין כי הזרקת תלות מתבצעת באמצעות מה שנקרא מיכלי Spring. ישנן שלוש דרכים להגדיר את מיכלי האביב:
  • שימוש בקובצי XML (שיטה מיושנת)
  • שימוש בהערות + קבצי XML (בדרך מודרנית)
  • שימוש בקוד Java (בדרך מודרנית)
אנו משתמשים כעת בתצורה באמצעות קבצי XML. למרות העובדה ששיטה זו נחשבת מיושנת, פרויקטים רבים עדיין נכתבים בצורה זו. לכן אתה צריך לדעת. ראשית, עליך ליצור קובץ xml בתיקיית המשאבים. אתה יכול לתת לזה כל שם, אבל רצוי בעל משמעות. קראתי לזה "applicationContext.xml". אביב.  שיעור 2. IoC / DI בפועל - 2 בקובץ זה נכתוב את קטע הקוד הבא (רשימה 10):
<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="javaDeveloper" class="org.example.JavaDevelopment"/>
    <bean id="pythonDeveloper" class="org.example.PythonDevelopment"/>

    <bean id="hiringDepartment" class="org.example.HiringDepartment">
        <constructor-arg ref="javaDeveloper"/>
    </bean>

</beans>
עכשיו, לפי הסדר. שמונה שורות הקוד הראשונות לא מעניינות אותנו, הן ברירת מחדל. אתה יכול פשוט להעתיק אותם. התג <bean> </bean> מגדיר שעועית Spring. שעועית היא אובייקט שנוצר ומנוהל על ידי מיכל Spring. במילים פשוטות, Spring container בעצמו יוצר עבורנו אובייקט מחלקה חדש (לדוגמה: JavaDevelopment javaDevelopment = new JavaDevelopment();). בתוך התג הזה יש תכונות מזהה ומחלקה. id מציין את שם השעועית. המזהה הזה ישמש לגישה לאובייקט. זה שווה ערך לשם של אובייקט במחלקת Java. class - מגדיר את שם המחלקה אליה קשור השעועית (האובייקט) שלנו. עליך לציין את הנתיב המלא לכיתה. שימו לב לעועית המשרד להשכרה. בתוך השעועית הזו יש עוד תג <constructor-arg ref="javaDeveloper"/>. כאן מתרחשת הזרקת תלות (במקרה שלנו, הזרקה באמצעות בנאי). <constructor-arg> - אומר ל-Spring שמיכל ה-Spring צריך לחפש תלות ב-class constructor המוגדר בתכונת bean. ואיזה אובייקט צריך להיות משויך נקבע על ידי תכונת ref , בתוך התג <constructor-arg>. ref - מציין את המזהה של השעועית למגע. אם ב-ref במקום javaDeveloper נציין את ה-id pythonDeveloper, אז החיבור מתרחש עם המחלקה PythonDevelopmen. כעת עלינו לתאר את הכיתה הראשית. זה ייראה כך: (רישום11)
package org.example;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String ... args){
        //Определяем контекст файл в котором содержатся прописанные нами бины
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //Получем бины, которые были определены в файле applicationContext.xml
        HiringDepartment hiringDepartment = context.getBean("hiringDepartment", HiringDepartment.class);

        hiringDepartment.displayInfo();

        context.close(); //Контекст всегда должен закрываться
    }
}
מה פה?
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
שורה זו מקשרת את ה-Main class לקובץ .xml שמתאר את השעועית שלנו. הערך המועבר לבנאי חייב להתאים לשם של קובץ ה-xml. (במקרה שלנו applicationContext.xml).
HiringDepartment hiringDepartment = context.getBean("hiringDepartment", HiringDepartment.class);
מציין שאנחנו רוצים לקבל שעועית (אובייקט) של הכיתה HiringDepartment. הארגומנט הראשון מצביע על ה-bean id שכתבנו בקובץ xml. הטיעון השני מצביע על הכיתה אליה אנו רוצים לפנות. תהליך זה נקרא השתקפות .
hiringDepartment.displayInfo();
 context.close(); //Контекст всегда должен закрываться
כאן אנו מקבלים בקלות שיטה של ​​מחלקה HiringDepartment. שימו לב שלא השתמשנו במילת המפתח החדשה להשגת האובייקטים, ולא הגדרנו אובייקטים תלויים מסוג JavaDevelopment או PythonDevelopment בשום מקום. הם תוארו בפשטות בקובץ applicationContext.xml. שימו לב גם לשורה האחרונה. אתה תמיד צריך לסגור את ההקשר לפני כיבוי. אחרת, משאבים לא ישוחררו, ועלולה להתרחש דליפת זיכרון או פעולה שגויה של התוכנית. אם יש לכם שאלות או הצעות, כתבו בתגובות, אני בהחלט אענה. תודה על תשומת הלב. קוד המקור בקישור My GitHub Cart תוכן הקורס להמשך...
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION