Dependency Injection และ Inversion of Control ใน Spring Framework คืออะไร?


112

"Dependency Injection" และ "Inversion of Control" มักถูกกล่าวถึงเป็นข้อดีหลักของการใช้ Spring framework สำหรับการพัฒนา Web framework

ใครช่วยอธิบายได้ไหมว่ามันคืออะไรด้วยตัวอย่างถ้าเป็นไปได้


อาจซ้ำกันได้ของInversion of Control คืออะไร?
Steve Chambers

3
@SteveChambers ไม่ซ้ำกันคำถามนี้ถูกถามใน Springs Perspective คำถามนั้นโดยทั่วไปแล้ว
VdeX

คำตอบ:


233
  • ฤดูใบไม้ผลิจะช่วยในการสร้างโปรแกรมคู่หลวมเนื่องจากการพึ่งพาการฉีด
  • ใน Spring ออบเจ็กต์จะกำหนดความสัมพันธ์ของพวกเขา (การอ้างอิง) และไม่ต้องกังวลว่าจะได้รับการอ้างอิงเหล่านั้นอย่างไร เป็นความรับผิดชอบของ Spring ในการจัดหาการอ้างอิงที่จำเป็นสำหรับการสร้างวัตถุ

ตัวอย่างเช่น : สมมติว่าเรามีวัตถุและมีการพึ่งพาวัตถุEmployee Addressเราจะกำหนดถั่วที่สอดคล้องกับการที่จะกำหนดพึ่งพาวัตถุEmployeeAddress

เมื่อ 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 สามารถทำได้โดยการฉีด setter หรือการฉีด constructor

ฉันไม่เห็นด้วย. ฉันไม่คิดว่านี่เป็นคำอธิบายที่ชัดเจน ทำไมคุณไม่สามารถสร้างอินสแตนซ์ "ที่อยู่" ภายใน "พนักงาน" แทนการใช้กรอบเพื่อสร้างและฉีดเข้าไป มีการเรียกตัวอย่างรายละเอียดเพิ่มเติมเล็กน้อย
Boris

2
@ บอริสไม่มีใครบอกว่าคุณไม่สามารถสร้างอินสแตนซ์วัตถุของคุณเองได้ แต่จุดประสงค์เพียงอย่างเดียวของคำตอบคือการแสดงให้เห็นว่าคุณจะบรรลุเป้าหมายเดียวกันกับ DI ได้อย่างไร คุณสามารถมีทั้ง DI และอ็อบเจ็กต์ที่สร้างอินสแตนซ์ด้วยรหัสไคลเอนต์ สิ่งนี้จะยังคงเรียกว่า IOC อย่างน้อยก็บางส่วน
bogdan.rusu


บอริส หึงมาก? นั่นเป็นคำตอบที่ดีที่สุด
Aniket Kapse

31

ฉันจะเขียนความเข้าใจง่ายๆของสองคำนี้: (เพื่อความเข้าใจอย่างรวดเร็วเพียงแค่อ่านตัวอย่าง)

  • 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 ผู้บริโภคซอฟต์แวร์ / อ็อบเจ็กต์จะได้รับการควบคุม / ตัวเลือกมากกว่าซอฟต์แวร์ / อ็อบเจ็กต์แทนที่จะถูกควบคุมหรือมีตัวเลือกน้อยลง

    การผกผันของการควบคุมเป็นแนวทางการออกแบบมีจุดประสงค์ดังต่อไปนี้:
    - มีการแยกส่วนของการดำเนินงานบางอย่างออกจากการนำไปใช้งาน
    - ทุกโมดูลสามารถมุ่งเน้นไปที่สิ่งที่ออกแบบมาเพื่อ
    - โมดูลไม่ตั้งสมมติฐานเกี่ยวกับสิ่งที่ระบบอื่น ๆ ทำ แต่อาศัยสัญญาของพวกเขา
    - การเปลี่ยนโมดูลไม่มีผลข้างเคียงกับโมดูลอื่น ๆ

ฉันจะเก็บสิ่งที่เป็นนามธรรมไว้ที่นี่คุณสามารถเยี่ยมชมลิงค์ต่อไปนี้เพื่อทำความเข้าใจรายละเอียดของหัวข้อ

อ่านดีพร้อมตัวอย่าง

คำอธิบายโดยละเอียด


11

ใน Spring Objects มีการเชื่อมต่อกันอย่างหลวม ๆ กล่าวคือแต่ละคลาสจะไม่ขึ้นอยู่กับกันและกันเพื่อให้ทุกอย่างสามารถทดสอบได้ทีละรายการ แต่เมื่อใช้คลาสเหล่านั้นคลาสอาจขึ้นอยู่กับคลาสอื่นซึ่งจำเป็นต้องสร้างอินสแตนซ์ก่อน

ดังนั้นเราจึงบอกสปริงว่าคลาส A ขึ้นอยู่กับคลาส B ดังนั้นเมื่อสร้าง bean (เช่นคลาส) สำหรับคลาส A มันจะสร้างอินสแตนซ์คลาส B ก่อนคลาส A และแทรกในคลาส A โดยใช้เมธอด setter หรือ constructor DI กล่าวคือเรากำลังบอกการพึ่งพาในช่วงรันไทม์ นี่คือ DI

ในขณะที่เรากำลังมอบหมายความรับผิดชอบในการสร้างวัตถุ (ถั่ว) การดูแลรักษาและการรวมตัวของพวกมันไปยัง Spring แทนที่จะเป็นการเข้ารหัสแบบยากเราจึงเรียกมันว่า Inversion Of Control (IOC)


7

การผกผันของการควบคุม (IOC):

IoCเป็นรูปแบบการออกแบบที่อธิบายถึงการย้อนกลับของการควบคุมในระบบดังนั้นขั้นตอนการดำเนินการจึงไม่ถูกควบคุมโดยโค้ดส่วนกลาง ซึ่งหมายความว่าส่วนประกอบควรขึ้นอยู่กับนามธรรมของส่วนประกอบอื่น ๆ เท่านั้นและไม่รับผิดชอบในการจัดการการสร้างวัตถุที่ขึ้นต่อกัน แต่อินสแตนซ์อ็อบเจ็กต์จะถูกจัดเตรียมที่รันไทม์โดยคอนเทนเนอร์ IoC ผ่าน Dependency Injection (DI)

IoC ช่วยให้ออกแบบซอฟต์แวร์ได้ดีขึ้นซึ่งอำนวยความสะดวกในการใช้ซ้ำการเชื่อมต่อแบบหลวมและการทดสอบส่วนประกอบซอฟต์แวร์ได้ง่าย

การพึ่งพาการฉีด (DI):

DIเป็นเทคนิคในการส่งผ่านการอ้างอิงไปยังตัวสร้างของวัตถุ หากอ็อบเจ็กต์ถูกโหลดจากคอนเทนเนอร์การอ้างอิงจะถูกจัดเตรียมโดยอัตโนมัติโดยคอนเทนเนอร์ สิ่งนี้ช่วยให้คุณใช้การพึ่งพาโดยไม่ต้องสร้างอินสแตนซ์ด้วยตนเอง ซึ่งจะช่วยลดการเชื่อมต่อและช่วยให้คุณสามารถควบคุมอายุการใช้งานของอินสแตนซ์ออบเจ็กต์ได้มากขึ้น

คลิกเพื่อดูเพิ่มเติม


6

Spring: Spring คือคอนเทนเนอร์“ Inversion of Control” สำหรับแพลตฟอร์ม Java

Inversion of Control (IoC): Inversion of Control (IoC) เป็นวิธีการเขียนโปรแกรมเชิงวัตถุโดยการเชื่อมต่อของอ็อบเจ็กต์จะถูก จำกัด ไว้ที่รันไทม์โดยอ็อบเจ็กต์ "แอสเซมเบลอร์" และโดยทั่วไปจะไม่ทราบเวลาคอมไพล์โดยใช้การวิเคราะห์แบบคงที่

Dependency Injection (DI): "Dependency injection เป็นรูปแบบการออกแบบซอฟต์แวร์ที่ช่วยให้สามารถลบการอ้างอิงแบบฮาร์ดโค้ดและทำให้สามารถเปลี่ยนแปลงได้ไม่ว่าจะเป็นในขณะรันไทม์หรือเวลาคอมไพล์" - วิกิ.


สิ่งนี้ง่ายกว่าที่มีอยู่แล้วอย่างไร (ซึ่งคำตอบนี้มีที่มาจากที่ใด) มันไม่ได้คำนึงถึงคำขอของ OP เพื่อความเรียบง่ายเว้นแต่การเสนอราคาสองครั้งรอบ ๆ คำศัพท์จะทำให้สิ่งต่างๆง่ายขึ้นอย่างน่าอัศจรรย์
Flame of udun

6

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 โดยให้สองวิธีในการฉีดการพึ่งพานี้

  1. การฉีด Setter

วิธีการ Setter ในคลาส Employee ซึ่งใช้การอ้างอิงของคลาส Address

public void setAddress(Address addr) {
    this.address = addr;
}
  1. การฉีดตัวสร้าง

Constructor ในคลาส Employee ซึ่งยอมรับ Address

Employee(Address addr) {
      this.address = addr;
}

ด้วยวิธีนี้ค่าคลาสที่อยู่สามารถตั้งค่าได้อย่างอิสระโดยใช้การฉีด setter / constructor


3

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

คุณสามารถอ่านบทความฉบับสมบูรณ์ได้ที่นี่


1

วิธีดั้งเดิมในการรับอินสแตนซ์ที่อยู่ใน Employee คือการสร้างอินสแตนซ์ใหม่ของคลาสที่อยู่ Spring สร้างอ็อบเจ็กต์ที่ต้องพึ่งพาทั้งหมดดังนั้นเราจึงไม่ต้องกังวลเกี่ยวกับวัตถุ

ดังนั้นในฤดูใบไม้ผลิเราก็ขึ้นอยู่กับภาชนะสปริงที่ให้วัตถุพึ่งพาแก่เรา


1

IOC เป็นเทคนิคที่คุณให้คนอื่นสร้างวัตถุให้คุณ และคนอื่นในกรณีของฤดูใบไม้ผลิคือภาชนะ IOC

Dependency Injection เป็นเทคนิคที่วัตถุหนึ่งให้การพึ่งพาของวัตถุอื่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.