ดังนั้น... ใน บทเรียน ที่แล้วเราได้ทบทวนส่วนทางทฤษฎีของ IoC และ DI โดยย่อ เรายังตั้งค่าไฟล์คอนฟิกูเรชัน pom.xml สำหรับโปรเจ็กต์ของเราด้วย วันนี้เราเริ่มสร้างส่วนหลักของโปรแกรม ก่อนอื่น ฉันจะแสดงวิธีสร้างโปรแกรมที่ไม่มี IoC / DI จากนั้นเราจะสร้างโปรแกรมที่แนะนำการพึ่งพาอย่างอิสระโดยตรง นั่นคือการควบคุมโค้ดจะส่งผ่านไปยังมือของเฟรมเวิร์ก (ฟังดูน่าขนลุก) ขณะที่เรากำลังจัดการโปรแกรม ลองจินตนาการว่ามีบริษัทแห่งหนึ่ง และบริษัท (ปัจจุบัน) มีสองแผนก: แผนก Java Development และ Hiring ให้ชั้นเรียนที่อธิบาย "Java Development Department" มีสองวิธี: String getName() - ส่งกลับชื่อพนักงาน, String getJob() - ส่งกลับตำแหน่งของพนักงาน (รายการ 1)
ใช่ ไม่มีใครห้าม “เหมืองและทุ่งหญ้า” แต่นั่นไม่ใช่มืออาชีพ Tyzh เป็นโปรแกรมเมอร์ และที่นี่คุณสามารถใช้ DI นั่นคือเราจะไม่ทำงานในระดับชั้นเรียน แต่ในระดับอินเทอร์เฟซ ตอนนี้สถานะของวัตถุของเราจะถูกเก็บไว้ในอินเทอร์เฟซ ด้วยวิธีนี้ การพึ่งพาระหว่างคลาสจะน้อยที่สุด ในการทำเช่นนี้ อันดับแรกเราสร้างอินเทอร์เฟซการพัฒนา ซึ่งมีสองวิธีในการอธิบายพนักงาน (รายการ 6)
ในไฟล์นี้เราจะเขียนโค้ดต่อไปนี้ (รายการ 10):
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 เราจะได้ผลลัพธ์ดังนี้:
Name: Alexa
Job: Middle Java developer
ตอนนี้ลองจินตนาการว่าบริษัทกำลังไปได้สวย ดังนั้นพวกเขาจึงตัดสินใจขยายขอบเขตกิจกรรมและเปิดแผนกพัฒนา Python และนี่คือคำถามที่เกิดขึ้น: จะอธิบายแผนกนี้ในระดับโปรแกรมได้อย่างไร? คำตอบ: คุณต้อง “คัดลอกและวาง” ทุกที่ที่คุณต้องการอธิบายแผนกนี้ (วิธีเก่าที่ดี🙃) ขั้นแรก เรามาสร้างคลาสขึ้นมาซึ่งจะอธิบายแผนก "Pythonists" (รายการ 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());
}
}
}
ดังที่เราเห็น จำนวนโค้ดเพิ่มขึ้นเป็นสองเท่าหรือมากกว่านั้น เมื่อมีโค้ดจำนวนมาก ความสามารถในการอ่านจะลดลง และสิ่งที่แย่ที่สุดคือเราสร้างออบเจ็กต์ทั้งหมดด้วยตนเอง และสร้างคลาสที่ต้องพึ่งพาซึ่งกันและกันในระดับสูง โอเค เราเห็นด้วยกับเรื่องนี้ พวกเขาอธิบายเพียงแผนกเดียว เราจะไม่สูญเสียสิ่งใดจากสิ่งนี้ แล้วถ้าเราเพิ่มแผนกอื่นล่ะ? แล้วถ้ามีสองคนล่ะ? สาม? แต่ไม่มีใครห้าม “การขุดและการแทะเล็มหญ้า” 
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());
}
}
ดังที่เราเห็นจำนวนโค้ดลดลง และที่สำคัญที่สุด การพึ่งพาอาศัยกันลดลง ค่านิยมและการพึ่งพาถูกนำไปใช้กับวัตถุเหล่านี้จริง ๆ อย่างไร? มีสามวิธีในการฉีดการพึ่งพา:
- การใช้ตัวสร้าง
- การใช้เซ็ตเตอร์
- การเดินสายอัตโนมัติ (การผูกอัตโนมัติ)
- การใช้ไฟล์ XML (วิธีที่ล้าสมัย)
- การใช้คำอธิบายประกอบ + ไฟล์ XML (สมัยใหม่)
- การใช้โค้ด Java (วิธีสมัยใหม่)

<?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 bean beanเป็นวัตถุที่สร้างและจัดการโดยคอนเทนเนอร์ Spring พูดง่ายๆ ก็คือ Spring Container เองก็สร้างคลาสอ็อบเจ็กต์ใหม่สำหรับเรา (เช่น JavaDevelopment javaDevelopment = new JavaDevelopment();) ภายในแท็กนี้มีแอตทริบิวต์ id และ class idระบุชื่อของถั่ว รหัสนี้จะใช้เพื่อเข้าถึงวัตถุ มันเทียบเท่ากับชื่อของวัตถุในคลาส Java class - กำหนดชื่อของคลาสที่ bean (วัตถุ) ของเราผูกไว้ คุณต้องระบุเส้นทางแบบเต็มไปยังชั้นเรียน ให้ความสนใจกับการจ้างงานแผนกถั่ว ภายใน bean นี้มีแท็ก <constructor-arg ref="javaDeveloper"/> อีกแท็กหนึ่ง นี่คือจุดที่การพึ่งพาการฉีดเกิดขึ้น (ในกรณีของเรา การฉีดโดยใช้ตัวสร้าง) <constructor-arg> - บอก Spring ว่า Spring Container ควรมองหาการพึ่งพาในตัวสร้างคลาสที่กำหนดไว้ในแอตทริบิวต์ bean และวัตถุใดที่ต้องเชื่อมโยงกับจะถูกกำหนดโดย แอตทริบิวต์ refภายในแท็ก <constructor-arg> ref - ระบุ id ของ bean ที่จะติดต่อ หากในการอ้างอิงแทนที่จะเป็น 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");
บรรทัดนี้เชื่อมโยงคลาส Main ไปยังไฟล์ .xml ที่อธิบายถั่วของเรา ค่าที่ส่งไปยังตัวสร้างจะต้องตรงกับชื่อของไฟล์ .xml (ในกรณีของเรา applicationContext.xml)
HiringDepartment hiringDepartment = context.getBean("hiringDepartment", HiringDepartment.class);
บ่งชี้ว่าเราต้องการรับ bean (วัตถุ) ของคลาส HiringDepartment อาร์กิวเมนต์แรกชี้ไปที่ bean id ที่เราเขียนไว้ในไฟล์ xml อาร์กิวเมนต์ที่สองชี้ไปที่คลาสที่เราต้องการติดต่อ กระบวนการนี้เรียกว่าการ สะท้อน
hiringDepartment.displayInfo();
context.close(); //Контекст всегда должен закрываться
ที่นี่เราเข้าใจวิธีการของคลาส HiringDepartment อย่างง่ายดาย โปรดทราบว่าเราไม่ได้ใช้คีย์เวิร์ดใหม่เพื่อรับอ็อบเจ็กต์ และเราไม่ได้กำหนดอ็อบเจ็กต์ที่ต้องพึ่งพาประเภท JavaDevelopment หรือ PythonDevelopment ทุกที่ มีการอธิบายไว้อย่างง่ายๆ ในไฟล์ applicationContext.xml ให้ความสนใจกับบรรทัดสุดท้ายด้วย คุณควรปิดบริบทก่อนที่จะปิดเครื่องเสมอ มิฉะนั้น ทรัพยากรจะไม่ถูกปล่อย และอาจเกิดหน่วยความจำรั่วหรือการทำงานของโปรแกรมไม่ถูกต้อง หากคุณมีคำถามหรือข้อเสนอแนะเขียนความคิดเห็นฉันจะตอบอย่างแน่นอน ขอบคุณสำหรับความสนใจ ซอร์สโค้ดที่ลิงก์เนื้อหาหลักสูตร My GitHub Cart มีต่อ...
GO TO FULL VERSION