首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 依賴注入 (DI) 深度實戰:構造器注入、Setter 注入、集合注入與 IOC 實戰案例

     編輯:Java 相關知識

Spring 依賴注入 (DI) 核心機制與實戰全解析

依賴注入 (Dependency Injection, DI) 是 Spring IOC 容器的核心功能,本質是「由容器負責建立對象依賴關係」。本文系統講解構造器注入、Setter 注入、集合類型注入、注入方式選擇策略,並以文檔管理系統、MVC 分層架構為實戰案例展示 IOC/DI 的工程價值。

一、兩大核心注入方式

1. 構造器注入

適用場景:強依賴、不可變對象、循環依賴檢測

<bean id="person" class="com.example.Person">
    <!-- 方式 A:按參數索引 -->
    <constructor-arg index="0" value="張三" />
    <constructor-arg index="1" ref="student" />
    
    <!-- 方式 B:按參數類型 (推薦,順序不敏感) -->
    <constructor-arg type="java.lang.String" value="李四" />
    <constructor-arg type="com.example.Student" ref="student" />
</bean>

要求:類必須提供對應參數的構造器,無參構造器可選。

2. Setter 注入 (主流方式)

適用場景:可選依賴、可變對象、屬性眾多、與框架整合 (如 JPA Entity)

<bean id="person" class="com.example.Person">
    <!-- 簡單類型 -->
    <property name="name" value="王五" />
    <property name="age" value="25" />
    
    <!-- 引用類型 -->
    <property name="student" ref="student" />
    
    <!-- 集合類型 -->
    <property name="lists">
        <list>
            <value>item1</value>
            <ref bean="student" />
        </list>
    </property>
    <property name="sets">
        <set><value>unique1</value></set>
    </property>
    <property name="maps">
        <map>
            <entry key="k1" value="v1" />
            <entry key="k2" ref="student" />
        </map>
    </property>
    <property name="props">
        <props>
            <prop key="p1">v1</prop>
        </props>
    </property>
</bean>

要求:類需提供無參構造器 + 對應 setter 方法。

二、注入方式選擇策略

維度構造器注入Setter 注入
依賴強度強依賴 (必須)弱依賴 (可選)
不可變性支援 final 字段字段不可為 final
循環依賴容器啟動時檢測報錯可解決循環依賴
可讀性參數多時構造器膨脹屬性名語意清晰
框架相容部分舊框架不支援通用標準

現代最佳實踐:構造器注入為主,Setter 注入為輔 (Spring 4+ 官方推薦)。

三、IOC/DI 工程價值實戰案例

案例 1:文檔管理系統 - 面向介面編程

// 介面
public interface Document { void read(); void write(); }

// 實現
@Component("wordDocument") public class WordDocument implements Document { ... }
@Component("pdfDocument") public class PDFDocument implements Document { ... }

// 管理類 - 依賴介面而非實現
@Component
public class DocumentManager {
    @Resource(name="pdfDocument") // 運行時靈活切換實現
    private Document document;
    public void read() { document.read(); }
}

核心價值:代碼中零硬編碼實現類,切換實現僅修改 XML/註解配置,實現真正的面向介面編程。

案例 2:MVC 三層架構解耦

// DAO 層
@Repository public class PersonDaoImpl implements PersonDao { ... }

// Service 層 - 依賴 DAO 介面
@Service
public class PersonServiceImpl implements PersonService {
    @Resource private PersonDao personDao; // 注入介面
    public void savePerson() { personDao.savePerson(); }
}

// Action/Controller 層 - 依賴 Service 介面
@Controller
public class PersonAction {
    @Resource private PersonService personService;
    public void savePerson() { personService.savePerson(); }
}

各層僅依賴上層介面,實現類由容器注入,單元測試時可輕鬆 Mock 介面。

四、Spring 繼承機制減少配置冗餘

<!-- 父 Bean 定義公共屬性 -->
<bean id="baseConfig" abstract="true">
    <property name="timeout" value="30000" />
    <property name="encoding" value="UTF-8" />
</bean>

<!-- 子 Bean 繼承並覆蓋 -->
<bean id="serviceA" class="com.example.ServiceA" parent="baseConfig">
    <property name="timeout" value="5000" /> <!-- 覆蓋 -->
</bean>
<bean id="serviceB" class="com.example.ServiceB" parent="baseConfig" /> <!-- 直接繼承 -->

五、容器啟動與注入執行順序

  1. 解析配置 (XML/註解/掃描)
  2. 實例化所有 Bean (構造器/工廠方法)
  3. 執行依賴注入 (Setter/構造器參數/自動裝配)
  4. 初始化回調 (InitializingBean.afterPropertiesSet()、@PostConstruct、init-method)
  5. Bean 就緒可用
  6. 容器關閉時銷毀回調 (DisposableBean.destroy()、@PreDestroy、destroy-method)

lazy-init="true 可延遲到首次獲取時初始化;depends-on 強制初始化順序。

六、總結

DI 不僅是「屬性賦值」,更是解耦合、可測試、可擴展的架構基石。掌握注入方式選擇、集合注入細節、IOC 容器生命周期,能讓您設計出更優雅、可維護的 Spring 應用架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved