"Dependency Injection" และ "Inversion of Control" มักถูกกล่าวถึงเป็นข้อดีหลักของการใช้ Spring framework สำหรับการพัฒนา Web framework
ใครช่วยอธิบายได้ไหมว่ามันคืออะไรด้วยตัวอย่างถ้าเป็นไปได้
"Dependency Injection" และ "Inversion of Control" มักถูกกล่าวถึงเป็นข้อดีหลักของการใช้ Spring framework สำหรับการพัฒนา Web framework
ใครช่วยอธิบายได้ไหมว่ามันคืออะไรด้วยตัวอย่างถ้าเป็นไปได้
คำตอบ:
ตัวอย่างเช่น : สมมติว่าเรามีวัตถุและมีการพึ่งพาวัตถุEmployee
Address
เราจะกำหนดถั่วที่สอดคล้องกับการที่จะกำหนดพึ่งพาวัตถุEmployee
Address
เมื่อ Spring พยายามสร้างEmployee
ออบเจ็กต์จะเห็นว่าEmployee
มีการพึ่งพาAddress
ดังนั้นก่อนอื่นจะสร้างAddress
อ็อบเจ็กต์ (อ็อบเจ็กต์ที่พึ่งพา) จากนั้นจึงฉีดเข้าไปในEmployee
อ็อบเจ็กต์
Inversion of Control ( IoC ) และ Dependency Injection ( DI ) ใช้แทนกันได้ IoC ทำได้โดย DI DI คือกระบวนการจัดหาการอ้างอิงและ IoC เป็นผลลัพธ์สุดท้ายของ DI ( หมายเหตุ: DI ไม่ใช่วิธีเดียวที่จะบรรลุ IoC แต่ยังมีวิธีอื่นด้วย)
โดย DI ความรับผิดชอบในการสร้างวัตถุเปลี่ยนจากรหัสแอปพลิเคชันของเราไปยัง Spring container ปรากฏการณ์นี้เรียกว่า IoC
ฉันจะเขียนความเข้าใจง่ายๆของสองคำนี้: (เพื่อความเข้าใจอย่างรวดเร็วเพียงแค่อ่านตัวอย่าง)
Dependency Injection (DI):
Dependency injection โดยทั่วไปหมายถึงการส่งผ่านวัตถุที่พึ่งพาเป็นพารามิเตอร์ไปยังวิธีการแทนที่จะให้วิธีการสร้างวัตถุที่ขึ้นต่อกัน
ความหมายในทางปฏิบัติคือวิธีการนี้ไม่มีการพึ่งพาโดยตรงกับการนำไปใช้งานเฉพาะ การใช้งานใด ๆ ที่ตรงตามข้อกำหนดสามารถส่งผ่านเป็นพารามิเตอร์ได้
ด้วยการใช้งานวัตถุนี้กำหนดการอ้างอิง และทำให้สปริงสามารถใช้ได้
สิ่งนี้นำไปสู่การพัฒนาแอปพลิเคชันควบคู่กันไปอย่างหลวม ๆ
ตัวอย่างโดยย่อ: วัตถุประสงค์ของพนักงานเมื่อสร้างขึ้นมันจะสร้างวัตถุที่อยู่โดยอัตโนมัติ (หากที่อยู่ถูกกำหนดให้เป็นการอ้างอิงโดยอ็อบเจ็กต์พนักงาน) *
คอนเทนเนอร์ Inversion of Control (IoC):
นี่เป็นลักษณะทั่วไปของเฟรมเวิร์กโดย IoC จะจัดการวัตถุจาวา
ตั้งแต่การสร้างอินสแตนซ์ไปจนถึงการทำลายผ่าน BeanFactory
- คอมโพเนนต์ Java ที่สร้างอินสแตนซ์โดยคอนเทนเนอร์ IoC เรียกว่า bean และคอนเทนเนอร์ IoC จัดการขอบเขตของ bean เหตุการณ์วงจรชีวิตและคุณสมบัติ AOP ใด ๆที่ได้รับการกำหนดค่าและเข้ารหัส QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it
.
ด้วยการใช้ Inversion of Control ผู้บริโภคซอฟต์แวร์ / อ็อบเจ็กต์จะได้รับการควบคุม / ตัวเลือกมากกว่าซอฟต์แวร์ / อ็อบเจ็กต์แทนที่จะถูกควบคุมหรือมีตัวเลือกน้อยลง
การผกผันของการควบคุมเป็นแนวทางการออกแบบมีจุดประสงค์ดังต่อไปนี้:
- มีการแยกส่วนของการดำเนินงานบางอย่างออกจากการนำไปใช้งาน
- ทุกโมดูลสามารถมุ่งเน้นไปที่สิ่งที่ออกแบบมาเพื่อ
- โมดูลไม่ตั้งสมมติฐานเกี่ยวกับสิ่งที่ระบบอื่น ๆ ทำ แต่อาศัยสัญญาของพวกเขา
- การเปลี่ยนโมดูลไม่มีผลข้างเคียงกับโมดูลอื่น ๆ
ฉันจะเก็บสิ่งที่เป็นนามธรรมไว้ที่นี่คุณสามารถเยี่ยมชมลิงค์ต่อไปนี้เพื่อทำความเข้าใจรายละเอียดของหัวข้อ
ใน Spring Objects มีการเชื่อมต่อกันอย่างหลวม ๆ กล่าวคือแต่ละคลาสจะไม่ขึ้นอยู่กับกันและกันเพื่อให้ทุกอย่างสามารถทดสอบได้ทีละรายการ แต่เมื่อใช้คลาสเหล่านั้นคลาสอาจขึ้นอยู่กับคลาสอื่นซึ่งจำเป็นต้องสร้างอินสแตนซ์ก่อน
ดังนั้นเราจึงบอกสปริงว่าคลาส A ขึ้นอยู่กับคลาส B ดังนั้นเมื่อสร้าง bean (เช่นคลาส) สำหรับคลาส A มันจะสร้างอินสแตนซ์คลาส B ก่อนคลาส A และแทรกในคลาส A โดยใช้เมธอด setter หรือ constructor DI กล่าวคือเรากำลังบอกการพึ่งพาในช่วงรันไทม์ นี่คือ DI
ในขณะที่เรากำลังมอบหมายความรับผิดชอบในการสร้างวัตถุ (ถั่ว) การดูแลรักษาและการรวมตัวของพวกมันไปยัง Spring แทนที่จะเป็นการเข้ารหัสแบบยากเราจึงเรียกมันว่า Inversion Of Control (IOC)
การผกผันของการควบคุม (IOC):
IoCเป็นรูปแบบการออกแบบที่อธิบายถึงการย้อนกลับของการควบคุมในระบบดังนั้นขั้นตอนการดำเนินการจึงไม่ถูกควบคุมโดยโค้ดส่วนกลาง ซึ่งหมายความว่าส่วนประกอบควรขึ้นอยู่กับนามธรรมของส่วนประกอบอื่น ๆ เท่านั้นและไม่รับผิดชอบในการจัดการการสร้างวัตถุที่ขึ้นต่อกัน แต่อินสแตนซ์อ็อบเจ็กต์จะถูกจัดเตรียมที่รันไทม์โดยคอนเทนเนอร์ IoC ผ่าน Dependency Injection (DI)
IoC ช่วยให้ออกแบบซอฟต์แวร์ได้ดีขึ้นซึ่งอำนวยความสะดวกในการใช้ซ้ำการเชื่อมต่อแบบหลวมและการทดสอบส่วนประกอบซอฟต์แวร์ได้ง่าย
การพึ่งพาการฉีด (DI):
DIเป็นเทคนิคในการส่งผ่านการอ้างอิงไปยังตัวสร้างของวัตถุ หากอ็อบเจ็กต์ถูกโหลดจากคอนเทนเนอร์การอ้างอิงจะถูกจัดเตรียมโดยอัตโนมัติโดยคอนเทนเนอร์ สิ่งนี้ช่วยให้คุณใช้การพึ่งพาโดยไม่ต้องสร้างอินสแตนซ์ด้วยตนเอง ซึ่งจะช่วยลดการเชื่อมต่อและช่วยให้คุณสามารถควบคุมอายุการใช้งานของอินสแตนซ์ออบเจ็กต์ได้มากขึ้น
Spring: Spring คือคอนเทนเนอร์“ Inversion of Control” สำหรับแพลตฟอร์ม Java
Inversion of Control (IoC): Inversion of Control (IoC) เป็นวิธีการเขียนโปรแกรมเชิงวัตถุโดยการเชื่อมต่อของอ็อบเจ็กต์จะถูก จำกัด ไว้ที่รันไทม์โดยอ็อบเจ็กต์ "แอสเซมเบลอร์" และโดยทั่วไปจะไม่ทราบเวลาคอมไพล์โดยใช้การวิเคราะห์แบบคงที่
Dependency Injection (DI): "Dependency injection เป็นรูปแบบการออกแบบซอฟต์แวร์ที่ช่วยให้สามารถลบการอ้างอิงแบบฮาร์ดโค้ดและทำให้สามารถเปลี่ยนแปลงได้ไม่ว่าจะเป็นในขณะรันไทม์หรือเวลาคอมไพล์" - วิกิ.
Inversion of control- หมายถึงการให้การควบคุมการสร้างและอินสแตนซ์ของถั่วสปริงไปยังคอนเทนเนอร์ Spring IOC และงานเดียวที่นักพัฒนาทำคือกำหนดค่า bean ในไฟล์ xml spring
การฉีดยาแบบพึ่งพา -
พิจารณาพนักงานระดับ
class Employee {
private int id;
private String name;
private Address address;
Employee() {
id = 10;
name="name";
address = new Address();
}
}
และพิจารณาที่อยู่ของชั้นเรียน
class Address {
private String street;
private String city;
Address() {
street="test";
city="test1";
}
}
ในโค้ดด้านบนค่าคลาสแอดเดรสจะถูกตั้งค่าก็ต่อเมื่อคลาสพนักงานถูกสร้างอินสแตนซ์เท่านั้นซึ่งขึ้นอยู่กับคลาสแอดเดรสในคลาสของพนักงาน และสปริงแก้ปัญหานี้โดยใช้แนวคิด Dependency Injection โดยให้สองวิธีในการฉีดการพึ่งพานี้
วิธีการ Setter ในคลาส Employee ซึ่งใช้การอ้างอิงของคลาส Address
public void setAddress(Address addr) {
this.address = addr;
}
Constructor ในคลาส Employee ซึ่งยอมรับ Address
Employee(Address addr) {
this.address = addr;
}
ด้วยวิธีนี้ค่าคลาสที่อยู่สามารถตั้งค่าได้อย่างอิสระโดยใช้การฉีด setter / constructor
Inversion of Control เป็นหลักการออกแบบทั่วไปของสถาปัตยกรรมซอฟต์แวร์ที่ช่วยในการสร้างเฟรมเวิร์กซอฟต์แวร์แบบโมดูลาร์ที่ใช้ซ้ำได้ซึ่งง่ายต่อการบำรุงรักษา
เป็นหลักการออกแบบที่ Flow of Control "ได้รับ" จากไลบรารีที่เขียนโดยทั่วไปหรือโค้ดที่ใช้ซ้ำได้
เพื่อให้เข้าใจได้ดียิ่งขึ้นมาดูวิธีที่เราใช้เขียนโค้ดในช่วงก่อนหน้าของการเขียนโค้ด ในภาษาขั้นตอน / ดั้งเดิมตรรกะทางธุรกิจโดยทั่วไปจะควบคุมการไหลของแอปพลิเคชันและ "เรียก" รหัส / ฟังก์ชันทั่วไปหรือที่ใช้ซ้ำได้ ตัวอย่างเช่นในแอปพลิเคชัน Console แบบธรรมดาขั้นตอนการควบคุมของฉันถูกควบคุมโดยคำสั่งของโปรแกรมซึ่งอาจรวมถึงการเรียกใช้ฟังก์ชันที่ใช้ซ้ำได้ทั่วไป
print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);
//More print and scan statements
<Do Something Interesting>
//Call a Library function to find the age (common code)
print Age
ในทางตรงกันข้ามกับ IoC Frameworks คือรหัสที่ใช้ซ้ำได้ซึ่ง "เรียก" ตรรกะทางธุรกิจ
ตัวอย่างเช่นในระบบที่ใช้ windows เฟรมเวิร์กจะพร้อมใช้งานเพื่อสร้างองค์ประกอบ UI เช่นปุ่มเมนูหน้าต่างและกล่องโต้ตอบ เมื่อฉันเขียนตรรกะทางธุรกิจของแอปพลิเคชันของฉันมันจะเป็นเหตุการณ์ของเฟรมเวิร์กที่จะเรียกรหัสตรรกะทางธุรกิจของฉัน (เมื่อเหตุการณ์ถูกไล่ออก) และไม่ใช่สิ่งที่ตรงกันข้าม
แม้ว่าโค้ดของเฟรมเวิร์กจะไม่ทราบถึงตรรกะทางธุรกิจของฉัน แต่ก็ยังรู้วิธีเรียกรหัสของฉัน สามารถทำได้โดยใช้เหตุการณ์ / ผู้ร่วมประชุมการโทรกลับ ฯลฯ ที่นี่การควบคุมโฟลว์คือ "กลับด้าน"
ดังนั้นแทนที่จะขึ้นอยู่กับการไหลของการควบคุมบนวัตถุที่มีขอบเขตคงที่การไหลขึ้นอยู่กับกราฟวัตถุโดยรวมและความสัมพันธ์ระหว่างวัตถุต่าง ๆ
Dependency Injection เป็นรูปแบบการออกแบบที่ใช้หลักการ IoC เพื่อแก้ไขการอ้างอิงของวัตถุ
พูดง่ายๆก็คือเมื่อคุณพยายามเขียนโค้ดคุณจะสร้างและใช้คลาสต่างๆ คลาสหนึ่ง (คลาส A) อาจใช้คลาสอื่น (คลาส B และ / หรือ D) ดังนั้นคลาส B และ D จึงเป็นการอ้างอิงของคลาส A
การเปรียบเทียบง่ายๆจะเป็นรถคลาส รถยนต์อาจขึ้นอยู่กับคลาสอื่น ๆ เช่นเครื่องยนต์ยางรถยนต์และอื่น ๆ
Dependency Injection แสดงให้เห็นว่าแทนที่จะสร้างคลาส Dependent (Class Car ที่นี่) สร้างการพึ่งพา (Class Engine และ Class Tyre) ควรฉีดคลาสด้วยอินสแตนซ์ที่เป็นรูปธรรมของการพึ่งพา
มาทำความเข้าใจกับตัวอย่างที่เป็นประโยชน์มากขึ้น พิจารณาว่าคุณกำลังเขียน TextEditor ของคุณเอง เหนือสิ่งอื่นใดคุณสามารถมีเครื่องตรวจตัวสะกดที่ให้ความสะดวกแก่ผู้ใช้ในการตรวจสอบการพิมพ์ผิดในข้อความของเขา การใช้งานโค้ดดังกล่าวอย่างง่ายสามารถ:
Class TextEditor
{
//Lot of rocket science to create the Editor goes here
EnglishSpellChecker objSpellCheck;
String text;
public void TextEditor()
{
objSpellCheck = new EnglishSpellChecker();
}
public ArrayList <typos> CheckSpellings()
{
//return Typos;
}
}
แรกเห็นทุกอย่างดูมีเลือดฝาด ผู้ใช้จะเขียนข้อความบางอย่าง นักพัฒนาจะจับข้อความและเรียกใช้ฟังก์ชัน CheckSpellings และจะพบรายการ Typos ที่เขาจะแสดงต่อผู้ใช้
ดูเหมือนว่าทุกอย่างจะใช้งานได้ดีจนกระทั่งวันดีคืนดีเมื่อผู้ใช้คนหนึ่งเริ่มเขียนภาษาฝรั่งเศสใน Editor
เพื่อให้การสนับสนุนสำหรับภาษาอื่น ๆ เราจำเป็นต้องมี SpellCheckers เพิ่มเติม อาจเป็นฝรั่งเศสเยอรมันสเปน ฯลฯ
ที่นี่เราได้สร้างโค้ดที่เชื่อมโยงอย่างแน่นหนาโดยมี SpellChecker "English" ซึ่งอยู่คู่กับคลาส TextEditor ของเราอย่างแน่นหนาซึ่งหมายความว่าคลาส TextEditor ของเราขึ้นอยู่กับ EnglishSpellChecker หรืออีกนัยหนึ่งคือ EnglishSpellCheker เป็นที่พึ่งพาสำหรับ TextEditor เราจำเป็นต้องลบการพึ่งพานี้ นอกจากนี้โปรแกรมแก้ไขข้อความของเราต้องการวิธีการอ้างอิงที่เป็นรูปธรรมของตัวตรวจสอบการสะกดใด ๆ ตามดุลยพินิจของผู้พัฒนาในขณะดำเนินการ
ดังที่เราเห็นในการแนะนำ DI มันชี้ให้เห็นว่าควรฉีดคลาสด้วยการอ้างอิง ดังนั้นควรเป็นความรับผิดชอบของรหัสการโทรในการฉีดการอ้างอิงทั้งหมดไปยังคลาส / รหัสที่เรียกว่า เราจึงสามารถปรับโครงสร้างโค้ดของเราเป็น
interface ISpellChecker
{
Arraylist<typos> CheckSpelling(string Text);
}
Class EnglishSpellChecker : ISpellChecker
{
public override Arraylist<typos> CheckSpelling(string Text)
{
//All Magic goes here.
}
}
Class FrenchSpellChecker : ISpellChecker
{
public override Arraylist<typos> CheckSpelling(string Text)
{
//All Magic goes here.
}
}
ในตัวอย่างของเราคลาส TextEditor ควรได้รับตัวอย่างที่เป็นรูปธรรมของประเภท ISpellChecker
ตอนนี้การพึ่งพาสามารถฉีดในตัวสร้างทรัพย์สินสาธารณะหรือวิธีการ
มาลองเปลี่ยนคลาสของเราโดยใช้ Constructor DI คลาส TextEditor ที่เปลี่ยนแปลงจะมีลักษณะดังนี้:
Class TextEditor
{
ISpellChecker objSpellChecker;
string Text;
public void TextEditor(ISpellChecker objSC)
{
objSpellChecker = objSC;
}
public ArrayList <typos> CheckSpellings()
{
return objSpellChecker.CheckSpelling();
}
}
เพื่อให้รหัสการโทรในขณะที่สร้างโปรแกรมแก้ไขข้อความสามารถฉีด SpellChecker Type ที่เหมาะสมไปยังอินสแตนซ์ของ TextEditor
คุณสามารถอ่านบทความฉบับสมบูรณ์ได้ที่นี่
วิธีดั้งเดิมในการรับอินสแตนซ์ที่อยู่ใน Employee คือการสร้างอินสแตนซ์ใหม่ของคลาสที่อยู่ Spring สร้างอ็อบเจ็กต์ที่ต้องพึ่งพาทั้งหมดดังนั้นเราจึงไม่ต้องกังวลเกี่ยวกับวัตถุ
ดังนั้นในฤดูใบไม้ผลิเราก็ขึ้นอยู่กับภาชนะสปริงที่ให้วัตถุพึ่งพาแก่เรา
IOC เป็นเทคนิคที่คุณให้คนอื่นสร้างวัตถุให้คุณ และคนอื่นในกรณีของฤดูใบไม้ผลิคือภาชนะ IOC
Dependency Injection เป็นเทคนิคที่วัตถุหนึ่งให้การพึ่งพาของวัตถุอื่น