JavaRush /Java blogi /Random-UZ /Bahor. Dars 2. Amalda IoC/DI
Umaralikhon
Daraja
Красноярск

Bahor. Dars 2. Amalda IoC/DI

Guruhda nashr etilgan
Va shunday ... Oldingi darsda biz IoC va DI ning nazariy qismini qisqacha ko'rib chiqdik. Loyihamiz uchun pom.xml konfiguratsiya faylini ham o'rnatdik. Bugun biz dasturning asosiy qismini yaratishni boshlaymiz. Birinchidan, men sizga IoC / DIsiz qanday qilib dastur yaratishni ko'rsataman. Va keyin biz to'g'ridan-to'g'ri bog'liqliklarni mustaqil ravishda kiritadigan dasturni yaratamiz. Ya'ni, kodni boshqarish ramka qo'liga o'tadi (qo'rqinchli tovushlar). Biz dasturni boshqarayotganimizda, ma'lum bir kompaniya borligini tasavvur qiling. Va kompaniyada (hozircha) ikkita bo'lim mavjud: Java rivojlantirish va ishga olish bo'limi. “Java Development Departamenti”ni tavsiflovchi sinf ikkita usulga ega bo'lsin: String getName() - xodim nomini qaytarish, String getJob() - xodimning pozitsiyasini qaytarish. (Ro'yxat 1)
package org.example;

public class JavaDevelopment {

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

    public String getJob(){
        return "Middle Java developer";
    }
}
Ishga qabul qilish bo'limini tavsiflovchi sinfda xodimni qabul qiladigan kiritish konstruktori va xodimlar haqidagi ma'lumotlarni aks ettiruvchi void displayInfo() usuli bo'lsin. (Ro'yxat 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());
    }
}
Bundan tashqari, Main - barcha bo'limlarni boshqaradigan sinf mavjud. (Ro'yxat 3)
package org.example;

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

        hiringDepartment.displayInfo();
    }
}
Hozircha barqarorlik. Main sinfini ishga tushirganimizda quyidagi natijaga erishamiz:
Name: Alexa
Job: Middle Java developer
Keling, kompaniyaning ajoyib ishlayotganini tasavvur qilaylik. Shuning uchun ular o'z faoliyat doirasini kengaytirishga qaror qilishdi va Python rivojlantirish bo'limini ochishdi. Va bu erda savol tug'iladi: ushbu bo'limni dastur darajasida qanday tasvirlash mumkin? Javob: ushbu bo'limni tasvirlash uchun kerakli joyga "nusxalash va joylashtirish" kerak (eski yaxshi usul🙃). Birinchidan, "Pythonists" bo'limini tavsiflovchi sinfni yarataylik. (Ro'yxat 4)
package org.example;

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

    public String getJob(){
        return "Middle Python developer";
    }
}
Va keyin biz uni Hiring Departmentga o'tkazamiz. Va HiringDepartment bu bo'lim haqida hech narsa aytmaydi. Shuning uchun siz PythonDevelopment sinfining yangi ob'ektini va Python dasturchilarini qabul qiladigan konstruktorni yaratishingiz kerak bo'ladi. Bundan tashqari, ma'lumotni to'g'ri ko'rsatishi uchun displayInfo() usulini o'zgartirishingiz kerak bo'ladi. (Ro'yxat 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());
        }
    }
}
Ko'rib turganimizdek, kod hajmi ikki baravar yoki undan ham ko'proq. Ko'p miqdorda kod bilan uning o'qilishi kamayadi. Va eng yomoni shundaki, biz barcha ob'ektlarni qo'lda yaratamiz va bir-biriga juda bog'liq bo'lgan sinflarni qilamiz. OK, biz bunga rozi bo'ldik. Ular faqat bitta bo'limni tasvirlab berishdi. Biz bundan hech narsa yo'qotmaymiz. Xo'sh, boshqa bo'limni qo'shsak-chi? Agar ikkita bo'lsa-chi? Uchmi? Ammo hech kim "kon qazish va yaylovni" taqiqlamagan. Bahor.  Dars 2. Amalda IoC / DI - 1 Ha, hech kim "Kon va yaylov" ni taqiqlamagan, ammo bu professional emas. Tyzh - dasturchi. Va bu erda siz DI dan foydalanishingiz mumkin. Ya'ni, biz sinf darajasida emas, balki interfeys darajasida ishlaymiz. Endi bizning ob'ektlarimizning holatlari interfeyslarda saqlanadi. Shunday qilib, sinflar orasidagi bog'liqliklar minimal bo'ladi. Buni amalga oshirish uchun biz birinchi navbatda xodimni tavsiflashning ikkita usuliga ega bo'lgan Development interfeysini yaratamiz. (Ro'yxat 6)
package org.example;

public interface Development {
    String getName();
    String getJob();
}
Keyin JavaDevelopment va PythonDevelopment ning ikkita klassi ushbu interfeysdan amalga oshirsin (meros olsin) va String getName() va String getJob() usullarini bekor qilsin. (Ro'yxat 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";
    }
}
Keyin HiringDepartment sinfida siz oddiygina Development tipidagi interfeys ob'ektini belgilashingiz mumkin va bunday ob'ektni konstruktorga o'tkazishingiz mumkin. (Ro'yxat 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());
    }
}
Ko'rib turganimizdek, kod miqdori kamaydi. Va eng muhimi, qaramliklar minimallashtirildi. Ushbu ob'ektlar uchun qiymatlar va bog'liqliklar qanday amalga oshiriladi? Qaramlikni in'ektsiya qilishning uchta usuli mavjud:
  • Konstruktordan foydalanish
  • Sozlagichlardan foydalanish
  • Avtomatik ulanish (avtomatik ulanish)
Konstruktor yordamida amalga oshirish Endi konstruktor yordamida amalga oshirish haqida gapiraylik. Listing 9ga qarang. HiringDepartment klassi konstruktori kiritish sifatida Development tipidagi ob'ektni kutadi. Biz ushbu konstruktor orqali bog'liqliklarni kiritishga harakat qilamiz. Shuni ham ta'kidlash kerakki, qaramlik in'ektsiyasi bahor deb ataladigan idishlar yordamida amalga oshiriladi. Spring konteynerlarini sozlashning uchta usuli mavjud:
  • XML fayllardan foydalanish (eskirgan usul)
  • Izohlar + XML fayllardan foydalanish (zamonaviy usul)
  • Java kodidan foydalanish (zamonaviy usul)
Endi biz konfiguratsiyadan XML fayllari yordamida foydalanmoqdamiz. Ushbu usul eskirgan deb hisoblanishiga qaramay, ko'plab loyihalar hali ham shu tarzda yoziladi. Shuning uchun siz bilishingiz kerak. Birinchidan, manbalar papkasida xml faylini yaratishingiz kerak. Siz unga har qanday nom berishingiz mumkin, lekin afzalroq ma'noli. Men uni "applicationContext.xml" deb nomladim. Bahor.  Dars 2. Amalda IoC / DI - 2 Ushbu faylda biz quyidagi kod qismini yozamiz (Ro'yxat 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>
Endi, tartibda. Kodning dastlabki sakkiz qatori biz uchun qiziq emas, ular sukut bo'yicha. Siz ularni oddiygina nusxalashingiz mumkin. <bean> </bean> tegi Bahor fasolini belgilaydi. Fasol - Spring konteyneri tomonidan yaratilgan va boshqariladigan ob'ekt. Oddiy so'z bilan aytganda, Spring konteynerining o'zi biz uchun yangi sinf ob'ektini yaratadi (masalan: JavaDevelopment javaDevelopment = new JavaDevelopment();). Ushbu teg ichida id va sinf atributlari mavjud. id loviya nomini belgilaydi. Ushbu identifikator ob'ektga kirish uchun ishlatiladi. Bu Java sinfidagi obyekt nomiga teng. sinf - bizning loviya (ob'ekt) bog'langan sinf nomini belgilaydi. Siz sinfga to'liq yo'lni belgilashingiz kerak. Ishga olish departamentiga e'tibor bering. Bu fasol ichida yana bir <constructor-arg ref="javaDeveloper"/> tegi mavjud. Bu erda qaramlik in'ektsiyasi sodir bo'ladi (bizning holatda, konstruktor yordamida in'ektsiya). <constructor-arg> - Spring-ga Spring konteyneri fasol atributida aniqlangan sinf konstruktorida bog'liqliklarni izlashi kerakligini aytadi. Qaysi ob'ekt bilan bog'lanishi kerakligi <constructor-arg> tegi ichidagi ref atributi bilan aniqlanadi. ref - aloqa uchun loviya identifikatorini ko'rsatadi. Agar javaDeveloper o'rniga ref da pythonDeveloper identifikatorini ko'rsatsak, u holda ulanish PythonDevelopmen klassi bilan sodir bo'ladi. Endi biz asosiy sinfni tasvirlashimiz kerak. Bu shunday ko'rinadi: (Ro'yxat 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(); //Контекст всегда должен закрываться
    }
}
Bu yerda nima bor?
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Bu satr Asosiy sinfni loviyalarimizni tavsiflovchi .xml fayliga bog'laydi. Konstruktorga berilgan qiymat .xml fayl nomiga mos kelishi kerak. (Bizning holimizda applicationContext.xml).
HiringDepartment hiringDepartment = context.getBean("hiringDepartment", HiringDepartment.class);
HiringDepartment sinfining fasolini (ob'ektini) olishni xohlayotganimizni bildiradi. Birinchi argument xml faylida biz yozgan fasol identifikatoriga ishora qiladi. Ikkinchi dalil biz bog'lanmoqchi bo'lgan sinfga ishora qiladi. Bu jarayon aks ettirish deb ataladi .
hiringDepartment.displayInfo();
 context.close(); //Контекст всегда должен закрываться
Bu erda biz HiringDepartment sinfining usulini osongina olamiz. E'tibor bering, biz ob'ektlarni olish uchun new kalit so'zidan foydalanmadik va JavaDevelopment yoki PythonDevelopment tipidagi bog'liq ob'ektlarni hech qanday joyda aniqlamadik. Ular oddiygina applicationContext.xml faylida tasvirlangan. Shuningdek, oxirgi qatorga e'tibor bering. O'chirishdan oldin har doim kontekstni yopishingiz kerak. Aks holda, resurslar bo'shatilmaydi va xotira oqishi yoki dasturning noto'g'ri ishlashi mumkin. Savollaringiz yoki takliflaringiz bo'lsa, sharhlarda yozing, men albatta javob beraman. E'tiboringiz uchun tashakkur. Manba kodi havolada Mening GitHub Cart Kurs tarkibi Davom etish uchun...
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION