JavaRush /Java блогу /Random-KY /Жаз. Сабак 2. IoC/DI практикада
Umaralikhon
Деңгээл
Красноярск

Жаз. Сабак 2. IoC/DI практикада

Группада жарыяланган
Ошентип... Мурунку сабакта IoC жана DIнин теориялык бөлүгүн кыскача карап чыктык. Ошондой эле биздин долбоор үчүн pom.xml конфигурация файлын орноттук. Бүгүн биз программанын негизги бөлүгүн түзө баштайбыз. Биринчиден, мен IoC / DI жок программаны кантип түзүүнү көрсөтөм. Анан биз түздөн-түз көз карандылыкты өз алдынча киргизген программаны түзөбүз. Башкача айтканда, codeду башкаруу алHowтын колуна өтөт (коркунучтуу угулат). Биз программаны башкарып жатканда, белгилүү бир компания бар деп элестетиңиз. Ал эми компанияда (азыр) эки бөлүм бар: Java өнүктүрүү жана жалдоо бөлүмү. "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());
    }
}
Ошондой эле негизги бар - бардык бөлүмдөрдү башкарган класс. (3-тизме)
package org.example;

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

        hiringDepartment.displayInfo();
    }
}
Азырынча стабилдүүлүк. Негизги классты иштеткенде биз төмөнкү натыйжаны алабыз:
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";
    }
}
Анан аны жалдоо департаментине өткөрүп беребиз. Ал эми HiringDepartment бул бөлүм жөнүндө эч нерсе айтпайт. Ошондуктан, сиз PythonDevelopment классынын жаңы an objectин жана 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());
        }
    }
}
Көрүнүп тургандай, codeдун көлөмү эки эсе көбөйдү, же андан да көп. Коддун чоң көлөмү менен анын окулушу төмөндөйт. Эң жаманы, биз бардык an objectтерди кол менен түзүп, бири-биринен өтө көз каранды класстарды жасайбыз. Макул, биз буга макул болдук. Алар жөн гана бир бөлүмдү сүрөттөп беришти. Биз мындан эч нерсе жоготпойбуз. Мейли, башка бөлүмдү кошсок кандай болот? Эки болсочу? Үч? Бирок эч ким «кен казууга жана мал жаюуга» тыюу салган эмес. Жаз.  2-сабак. IoC/DI практикада - 1 Ооба, “Кен жана жайытка” эч ким тыюу салган эмес, бирок бул профессионалдуу эмес. Тыж — программист. Жана бул жерде сиз DI колдоно аласыз. Башкача айтканда, биз класстык деңгээлде эмес, интерфейстик деңгээлде иштейбиз. Эми биздин an objectтердин абалы интерфейстерде сакталат. Ошентип, класстар ортосундагы көз карандылык минималдуу болот. Бул үчүн, биз алгач Кызматкерди сүрөттөөнүн эки ыкмасы бар Өнүктүрүү интерфейсин түзөбүз. (Листинг 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 түрүндөгү интерфейс an objectисин аныктай аласыз жана ошондой эле мындай an objectти конструкторго өткөрүп бере аласыз. (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());
    }
}
Көрүнүп тургандай, codeдун көлөмү азайды. Эң негизгиси, көз карандылык минималдуу болду. Бул an objectтер үчүн баалуулуктар жана көз карандылыктар чындыгында кантип ишке ашырылат? Көз карандылыкты киргизүүнүн үч жолу бар:
  • Конструкторду колдонуу
  • Жөндөөчүлөрдү колдонуу
  • Autowiring (автоматтык түрдө туташтыруу)
Конструктордун жардамы менен ишке ашыруу Эми конструктордун жардамы менен ишке ашыруу жөнүндө сүйлөшөлү. 9-Листингди караңыз. HiringDepartment классынын конструктору иштеп чыгуу түрүндөгү an objectти киргизүү катары күтөт. Биз бул конструктор аркылуу көз карандылыкты киргизүүгө аракет кылабыз. Ошондой эле, көз карандылыкты инъекциялоо жазгы идиштер деп аталгандарды колдонуу менен жүргүзүлөрүн белгилей кетүү керек. Жазгы контейнерлерди конфигурациялоонун үч жолу бар:
  • XML файлдарын колдонуу (эскирген ыкма)
  • Аннотацияларды + XML файлдарын колдонуу (Заманбап ыкма)
  • Java codeун колдонуу (Заманбап жол)
Биз азыр конфигурацияны XML файлдарын колдонуп жатабыз. Бул ыкма эскирген деп эсептелгенине карабастан, көптөгөн долбоорлор дагы эле ушундай жол менен жазылган. Ошондуктан бorш керек. Биринчиден, сиз ресурстар папкасында xml файлын түзүшүңүз керек. Сиз ага каалаган ат бере аласыз, бирок жакшыраак мааниси бар. Мен аны "applicationContext.xml" деп атадым. Жаз.  2-сабак. IoC/DI практикада - 2 Бул файлга биз codeдун төмөнкү бөлүгүн жазабыз (Листинг 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 контейнери тарабынан түзүлгөн жана башкарылуучу an object. Жөнөкөй сөз менен айтканда, Spring контейнеринин өзү биз үчүн жаңы класс an objectин түзөт (мисалы: JavaDevelopment javaDevelopment = new JavaDevelopment();). Бул тегдин ичинде id жана класс атрибуттары бар. id буурчактын атын аныктайт. Бул id an objectке кирүү үчүн колдонулат. Бул Java классындагы an objectтин атына барабар. класс - биздин буурчак (an object) байланган класстын атын аныктайт. Сиз класска толук жолду көрсөтүшүңүз керек. Ишке алуу департаментине көңүл буруңуз. Бул буурчактын ичинде дагы бир <constructor-arg ref="javaDeveloper"/> теги бар. Бул жерде көз карандылык инъекциясы пайда болот (биздин учурда конструктордун жардамы менен инъекция). <constructor-arg> - Жазга Spring контейнери фасоль атрибутунда аныкталган класс конструкторунан көз карандылыктарды издөө керектигин айтат. Жана кайсы an object менен байланыштыруу керектиги ref атрибуту менен аныкталат , <constructor-arg> теги. ref - байланыша турган буурчактын идентификаторун көрсөтөт. Эгерде ref'де javaDeveloper ордуна биз id pythonDeveloper көрсөтсөк, анда байланыш PythonDevelopmen классы менен ишке ашат. Эми биз Негизги классты сүрөттөшүбүз керек. Бул төмөнкүдөй болот: (Listing11)
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");
Бул сап Негизги классты биздин буурчактарды сүрөттөгөн .xml файлына байланыштырат. Конструкторго берилген маани .xml файлынын атына дал келиши керек. (Биздин учурда applicationContext.xml).
HiringDepartment hiringDepartment = context.getBean("hiringDepartment", HiringDepartment.class);
HiringDepartment классынын төө буурчакты (an objectисин) алгыбыз келгенин көрсөтөт. Биринчи аргумент биз xml файлында жазган буурчак идентификаторун көрсөтөт. Экинчи аргумент биз байланышкыбыз келген классты көрсөтөт. Бул процесс рефлексия деп аталат .
hiringDepartment.displayInfo();
 context.close(); //Контекст всегда должен закрываться
Бул жерде биз HiringDepartment классынын ыкмасын оңой алабыз. Объекттерди алуу үчүн биз new ачкыч сөзүн колдонгон жокпуз жана JavaDevelopment же PythonDevelopment түрүндөгү көз каранды an objectтерди эч жерде аныктаган жокпуз. Алар жөн гана applicationContext.xml файлында сүрөттөлгөн. Акыркы сапка да көңүл буруңуз. Өчүрүүдөн мурун контекстти дайыма жабуу керек. Болбосо, ресурстар бошотулbyte жана эс тутумдун агып кетиши же программанын туура эмес иштеши мүмкүн. Суроолоруңуз же сунуштарыңыз болсо комментарийге жазыңыз, мен сөзсүз жооп берем. Көңүл бурганыңыздарга рахмат. Булак codeу шилтемедеги My GitHub Cart Курстун мазмуну Улантылат...
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION