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

Spring 依賴注入深度解析:建構子注入、Setter 注入與 p-namespace 配置

     編輯:Java 相關知識

依賴注入 (DI) 核心思想

控制反轉 (IoC) 將對象創建與依賴管理權交給容器。DI 是 IoC 的具體實現方式:

  • 傳統方式:類內部 new 依賴,強耦合,難測試
  • DI 方式:依賴由外部注入,類只聲明需求,鬆耦合,易測試
// 傳統:強耦合
public class TextEditor {
    private SpellChecker spellChecker = new SpellChecker(); // 內部創建
}

// DI:鬆耦合
public class TextEditor {
    private SpellChecker spellChecker;
    public TextEditor(SpellChecker spellChecker) {  // 建構子注入
        this.spellChecker = spellChecker;
    }
    public void setSpellChecker(SpellChecker spellChecker) {  // Setter 注入
        this.spellChecker = spellChecker;
    }
}

方式一:建構子注入

透過建構子參數注入依賴,適合強制依賴、不可變對象。

XML 配置

<bean id="textEditor" class="com.example.di.TextEditor">
    <constructor-arg ref="spellChecker"/>
</bean>
<bean id="spellChecker" class="com.example.di.SpellChecker"/>

參數解析規則

情境解決方案範例
單一參數 直接匹配 <constructor-arg ref="bean"/>
多參數、類型不同 按聲明順序匹配 <constructor-arg ref="a"/><constructor-arg ref="b"/>
多參數、類型相同 指定 type 或 index <constructor-arg type="int" value="2024"/>
<constructor-arg type="java.lang.String" value="name"/>
明確指定位置 index 屬性 (0-based) <constructor-arg index="0" value="2024"/>

值 vs 參考

  • ref="beanId":注入其他 Bean 實例
  • value="literal":注入字面值 (基本類型、String)

方式二:Setter 注入

透過 Setter 方法注入,適合可選依賴、可變對象、循環依賴場景。

XML 配置

<bean id="textEditor" class="com.example.di.TextEditor">
    <property name="spellChecker" ref="spellChecker"/>
</bean>
<bean id="spellChecker" class="com.example.di.SpellChecker"/>

命名慣例

屬性名 spellChecker → Setter setSpellChecker(),遵循 JavaBean 規範。

方式三:p-namespace 簡化配置

Spring 2.0+ 提供 p: 命名空間,屬性注入更簡潔。

傳統 vs p-namespace

<!-- 傳統 -->
<bean id="john" class="com.example.Person">
    <property name="name" value="John Doe"/>
    <property name="spouse" ref="jane"/>
</bean>

<!-- p-namespace -->
<beans xmlns:p="https://www.springframework.org/schema/p" ...>
    <bean id="john" class="com.example.Person" 
          p:name="John Doe" p:spouse-ref="jane"/>
    <bean name="jane" class="com.example.Person" p:name="Jane Doe"/>
</beans>

關鍵語法

  • p:propertyName="value":字面值注入
  • p:propertyName-ref="beanId":Bean 參考注入 (-ref 後綴)

兩種方式比較與選擇指南

維度建構子注入Setter 注入
依賴性質強制、不可變可選、可變
不可變性支援 final 欄位不支援
循環依賴無法解決可解決
可讀性依賴集中在建構子分散在多個 Setter
向後相容新增參數破壞相容新增 Setter 不影響
Spring 團隊建議推薦 (Spring 4.0+)次要選擇

最佳實踐建議

  1. 預設使用建構子注入:確保 Bean 創建時狀態完整、支援不可變性
  2. 可選依賴用 Setter 或 @Autowired(required=false)
  3. 避免循環依賴:重構設計,或用 Setter/Field 注入打破循環
  4. 現代專案改用註解:@Autowired、@Required、@Value、建構子單參數可省略 @Autowired
  5. 配置外部化:@Value("${prop.name}") 讀取 properties/yml

完整範例程式碼

// SpellChecker.java
public class SpellChecker {
    public SpellChecker() { System.out.println("SpellChecker created"); }
    public void checkSpelling() { System.out.println("Checking..."); }
}

// TextEditor.java (建構子注入版)
public class TextEditor {
    private final SpellChecker spellChecker;
    public TextEditor(SpellChecker spellChecker) {  // 單參數建構子,Spring 4.0+ 自動注入
        this.spellChecker = spellChecker;
    }
    public void spellCheck() { spellChecker.checkSpelling(); }
}

// beans.xml
<bean id="spellChecker" class="com.example.di.SpellChecker"/>
<bean id="textEditor" class="com.example.di.TextEditor">
    <constructor-arg ref="spellChecker"/>
</bean>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved