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