Spring中Dependency Injection与@Autowire的关系及DI面试答疑
Great question! Let's break this down into clear, easy-to-grasp parts:
What is Dependency Injection?
First, it's useful to link DI to Inversion of Control (IoC)—DI is the most widely used implementation of the IoC principle.
At its core, Dependency Injection is a design pattern where:
- A class never creates its own required dependencies (no hardcoding
newto instantiate objects it needs). - Instead, those dependencies are "injected" into the class from an external source (via a constructor, method parameter, or property setter).
Put simply, we flip control of dependency creation: the class stops being responsible for making its own dependencies, and something outside the class handles that work and passes them in.
Concrete Example: Spell Checker for a Text Editor
Let’s expand on the spell checker example you mentioned to make this tangible. Here’s a complete code snippet showing constructor injection (one of the most common DI styles):
// Define an interface for spell checkers (abstraction over concrete tools) public interface IocSpellChecker { boolean checkSpelling(String text); } // A concrete implementation for English spelling checks public class EnglishSpellChecker implements IocSpellChecker { @Override public boolean checkSpelling(String text) { // Real spelling logic would go here—this is a simple placeholder return text.matches("[a-zA-Z\\s,.!?]+"); } } // TextEditor class that relies on a spell checker public class TextEditor { private IocSpellChecker checker; // Dependency is injected via the constructor—TextEditor doesn't create it itself! public TextEditor(IocSpellChecker checker) { this.checker = checker; } public void validateDocument(String document) { boolean isSpellingValid = checker.checkSpelling(document); System.out.println("Document spelling status: " + (isSpellingValid ? "Valid" : "Invalid")); } } // Usage: External code creates the dependency and injects it public class AppRunner { public static void main(String[] args) { IocSpellChecker englishChecker = new EnglishSpellChecker(); TextEditor editor = new TextEditor(englishChecker); editor.validateDocument("Hello, this is a test document with correct spelling!"); } }
In this example, TextEditor only cares about the IocSpellChecker interface—it has no clue which concrete implementation (English, Spanish, etc.) it’s using. The dependency is handed to it at runtime.
Why Use Dependency Injection?
DI solves several critical pain points in software development:
- Loose Coupling: Classes depend on abstractions (interfaces) instead of rigid concrete implementations. If we later need a
SpanishSpellChecker, we just implement the interface and inject it intoTextEditor—no changes to theTextEditorclass itself are needed. - Superior Testability: We can easily inject mock objects for unit testing. For example, instead of using a real spell checker, we could pass a mock that returns predefined results to test
TextEditor's logic in isolation. - Cleaner Separation of Concerns: Classes focus on their core job (like
TextEditorhandling document editing) instead of wasting code on creating and managing dependencies. - Flexibility & Reusability: Dependencies can be reused across multiple classes, and we can swap implementations at runtime without breaking dependent code.
内容的提问来源于stack exchange,提问作者New2Java

