JavaRush /Blog Java /Random-MS /Musim bunga. Pelajaran 2. IoC/DI dalam amalan
Umaralikhon
Tahap
Красноярск

Musim bunga. Pelajaran 2. IoC/DI dalam amalan

Diterbitkan dalam kumpulan
Dan sebagainya... Dalam pelajaran sebelumnya, kami mengkaji secara ringkas bahagian teori IoC dan DI. Kami juga menyediakan fail konfigurasi pom.xml untuk projek kami. Hari ini kita mula membuat bahagian utama program. Pertama, saya akan menunjukkan kepada anda cara membuat program tanpa IoC / DI. Dan kemudian kami akan terus mencipta program yang memperkenalkan kebergantungan secara bebas. Iaitu, kawalan kod itu dihantar ke tangan rangka kerja (bunyi menyeramkan). Semasa kami menguruskan program, bayangkan ada syarikat tertentu. Dan syarikat itu (buat masa ini) mempunyai dua jabatan: Jabatan Pembangunan dan Penyewaan Java. Biarkan kelas yang menerangkan "Jabatan Pembangunan Java" mempunyai dua kaedah: String getName() - mengembalikan nama pekerja, String getJob() - mengembalikan kedudukan pekerja. (Penyenaraian 1)
package org.example;

public class JavaDevelopment {

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

    public String getJob(){
        return "Middle Java developer";
    }
}
Biarkan kelas yang menerangkan jabatan pengambilan pekerja mempunyai pembina input yang menerima pekerja, dan kaedah void displayInfo() yang memaparkan maklumat tentang pekerja. (Penyenaraian 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());
    }
}
Terdapat juga Utama - kelas yang menguruskan semua jabatan. (Penyenaraian 3)
package org.example;

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

        hiringDepartment.displayInfo();
    }
}
Kestabilan buat masa ini. Apabila kami menjalankan kelas Utama kami mendapat hasil berikut:
Name: Alexa
Job: Middle Java developer
Sekarang mari kita bayangkan bahawa syarikat itu berjalan dengan baik. Oleh itu, mereka memutuskan untuk meluaskan skop aktiviti mereka dan membuka jabatan pembangunan Python. Dan di sini timbul persoalan: Bagaimana untuk menerangkan jabatan ini di peringkat program? Jawapan: anda perlu "salin dan tampal" di mana sahaja anda perlu menerangkan jabatan ini (kaedah lama yang baik🙃). Mula-mula, mari kita cipta kelas itu sendiri, yang akan menerangkan jabatan "Pythonists". (Penyenaraian 4)
package org.example;

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

    public String getJob(){
        return "Middle Python developer";
    }
}
Dan kemudian kami akan memindahkannya ke HiringDepartment. Dan HiringDepartment tidak mengatakan apa-apa tentang jabatan ini. Oleh itu, anda perlu mencipta objek baharu kelas PythonDevelopment dan pembina yang menerima pembangun Python. Anda juga perlu menukar kaedah displayInfo() supaya ia memaparkan maklumat dengan betul. (Penyenaraian 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());
        }
    }
}
Seperti yang kita lihat, jumlah kod telah meningkat dua kali ganda, atau lebih. Dengan jumlah kod yang banyak, kebolehbacaannya berkurangan. Dan perkara yang paling teruk ialah kami mencipta semua objek secara manual dan membuat kelas yang sangat bergantung antara satu sama lain. Ok, kami bersetuju dengan ini. Mereka hanya menerangkan satu jabatan. Kami tidak akan kehilangan apa-apa daripada ini. Nah, bagaimana jika kita menambah jabatan lain? Bagaimana jika ada dua? tiga? Tetapi tiada siapa yang melarang "perlombongan dan ragut." Musim bunga.  Pelajaran 2. IoC / DI dalam amalan - 1 Ya, tiada siapa yang melarang "Mine and Pasture", tetapi ia tidak profesional. Tyzh adalah seorang pengaturcara. Dan di sini anda boleh menggunakan DI. Iaitu, kami tidak akan bekerja di peringkat kelas, tetapi di peringkat antara muka. Sekarang keadaan objek kami akan disimpan dalam antara muka. Dengan cara ini, kebergantungan antara kelas akan menjadi minimum. Untuk melakukan ini, kami mula-mula mencipta antara muka Pembangunan, yang mempunyai dua kaedah untuk menerangkan pekerja. (Penyenaraian 6)
package org.example;

public interface Development {
    String getName();
    String getJob();
}
Biarkan dua kelas JavaDevelopment dan PythonDevelopment melaksanakan (warisan) daripada antara muka ini dan mengatasi kaedah String getName() dan String getJob(). (Penyenaraian 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";
    }
}
Kemudian dalam kelas HiringDepartment anda hanya boleh menentukan objek antara muka jenis Pembangunan dan anda juga boleh menghantar objek sedemikian kepada pembina. (Penyenaraian 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());
    }
}
Seperti yang kita lihat, jumlah kod telah berkurangan. Dan yang paling penting, kebergantungan telah diminimumkan. Bagaimanakah nilai dan kebergantungan sebenarnya dilaksanakan untuk objek ini? Terdapat tiga cara untuk melakukan suntikan pergantungan:
  • Menggunakan pembina
  • Menggunakan setter
  • Autowiring (pengikatan automatik)
Pelaksanaan menggunakan pembina Sekarang mari kita bercakap tentang pelaksanaan menggunakan pembina. Lihat Penyenaraian 9. Pembina kelas HiringDepartment mengharapkan objek jenis Pembangunan sebagai input. Kami akan cuba menyuntik kebergantungan melalui pembina ini. Ia juga perlu diperhatikan bahawa suntikan kebergantungan dilakukan menggunakan bekas Spring yang dipanggil. Terdapat tiga cara untuk mengkonfigurasi bekas Spring:
  • Menggunakan fail XML (kaedah lapuk)
  • Menggunakan anotasi + fail XML (Cara moden)
  • Menggunakan kod Java (cara moden)
Kami kini menggunakan konfigurasi menggunakan fail XML. Walaupun kaedah ini dianggap ketinggalan zaman, banyak projek masih ditulis dengan cara ini. Oleh itu anda perlu tahu. Pertama, anda mesti mencipta fail xml dalam folder sumber. Anda boleh memberikan apa-apa nama, tetapi sebaiknya nama yang bermakna. Saya memanggilnya "applicationContext.xml". Musim bunga.  Pelajaran 2. IoC / DI dalam amalan - 2 Dalam fail ini kami akan menulis sekeping kod berikut (Penyenaraian 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>
Sekarang, mengikut urutan. Lapan baris pertama kod tidak menarik bagi kami, ia adalah lalai. Anda hanya boleh menyalinnya. Teg <bean> </bean> mentakrifkan Spring bean. Kacang ialah objek yang dicipta dan diuruskan oleh bekas Spring. Dalam perkataan mudah, bekas Spring itu sendiri mencipta objek kelas baharu untuk kami (contohnya: JavaDevelopment javaDevelopment = new JavaDevelopment();). Di dalam teg ini terdapat id dan atribut kelas. id menyatakan nama kacang. Id ini akan digunakan untuk mengakses objek. Ia bersamaan dengan nama objek dalam kelas Java. kelas - mentakrifkan nama kelas yang diikat oleh kacang (objek) kita. Anda mesti menentukan laluan penuh ke kelas. Beri perhatian kepada kacang Jabatan yang mengupah. Di dalam kacang ini terdapat satu lagi tag <constructor-arg ref="javaDeveloper"/>. Di sinilah suntikan pergantungan berlaku (dalam kes kami, suntikan menggunakan pembina). <constructor-arg> - memberitahu Spring bahawa bekas Spring harus mencari kebergantungan dalam pembina kelas yang ditakrifkan dalam atribut kacang. Dan objek mana yang perlu dikaitkan ditentukan oleh ref attribute , di dalam tag <constructor-arg>. ref - menunjukkan id kacang untuk dihubungi. Jika dalam ref dan bukannya javaDeveloper kami menentukan id pythonDeveloper, maka sambungan berlaku dengan kelas PythonDevelopmen. Sekarang kita perlu menerangkan kelas Utama. Ia akan kelihatan seperti ini: (Penyenaraian11)
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(); //Контекст всегда должен закрываться
    }
}
Apa yang ada di sini?
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Baris ini memautkan kelas Utama ke fail .xml yang menerangkan kacang kami. Nilai yang dihantar kepada pembina mesti sepadan dengan nama fail .xml. (Dalam kes kami applicationContext.xml).
HiringDepartment hiringDepartment = context.getBean("hiringDepartment", HiringDepartment.class);
Menunjukkan bahawa kami ingin menerima kacang (objek) kelas HiringDepartment. Argumen pertama menunjuk kepada id kacang yang kami tulis dalam fail xml. Hujah kedua menunjukkan kelas yang ingin kita hubungi. Proses ini dipanggil refleksi .
hiringDepartment.displayInfo();
 context.close(); //Контекст всегда должен закрываться
Di sini kita dengan mudah mendapatkan kaedah kelas HiringDepartment. Ambil perhatian bahawa kami tidak menggunakan kata kunci baharu untuk mendapatkan objek, dan kami tidak mentakrifkan objek bergantung jenis JavaDevelopment atau PythonDevelopment di mana-mana sahaja. Ia hanya diterangkan dalam fail applicationContext.xml. Juga perhatikan baris terakhir. Anda harus sentiasa menutup konteks sebelum menutup. Jika tidak, sumber tidak akan dibebaskan, dan kebocoran memori atau pengendalian program yang salah mungkin berlaku. Jika anda mempunyai soalan atau cadangan, tulis dalam komen, saya pasti akan menjawab. Terima kasih atas perhatian. Kod sumber pada pautan Kandungan Kursus Troli GitHub Saya Akan diteruskan...
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION