| 模式 | 匹配規則 | 適用場景 | 風險點 |
|---|---|---|---|
no(默認) | 手動 <ref> 指定 | 完全可控、避免歧義 | 配置冗長 |
byName | 屬性名 = Bean ID | 命名規範、Bean ID 語義化 | 重構屬性名易破壞裝配 |
byType | 屬性類型 = Bean 類型(唯一) | 單一實現類、接口唯一實現 | 多實現拋 NoUniqueBeanDefinitionException |
constructor | 構造器參數類型匹配 | 不可變對象、強依賴注入 | 無匹配構造器拋異常 |
autodetect | 有構造器→constructor,否→byType | 兼容舊代碼 | 行為不確定,不推薦 |
default | 繼承父 <beans default-autowire> | 統一項目級默認策略 | 隱式行為難追蹤 |
public class Computer {
private Host host;
private Display display;
public Computer() {} // 無參構造器(byType/autodetect 需要)
public Computer(Host host, Display display) { // 有參構造器
this.host = host; this.display = display;
}
// getter/setter 省略
public void run() { System.out.println(host.run() + ", " + display.run()); }
}
public class Host { public String run() { return "主機運行中"; } }
public class Display { public String run() { return "顯示器運行中"; } }
<beans default-autowire="autodetect">
<bean id="host" class="com.redoffice.Host"/>
<bean id="display" class="com.redoffice.Display"/>
<!-- byName:屬性名 host/display 需與 bean id 一致 -->
<bean id="computer1" class="com.redoffice.Computer" autowire="byName"/>
<!-- byType:類型 Host/Display 在容器中唯一 -->
<bean id="computer2" class="com.redoffice.Computer" autowire="byType"/>
<!-- default:繼承 default-autowire="autodetect" -->
<bean id="computer3" class="com.redoffice.Computer" autowire="default"/>
<!-- autodetect:有有參構造器→constructor -->
<bean id="computer4" class="com.redoffice.Computer" autowire="autodetect"/>
<!-- constructor:顯式指定構造器參數(推薦) -->
<bean id="computer5" class="com.redoffice.Computer" autowire="constructor">
<constructor-arg index="0" ref="host"/>
<constructor-arg index="1" ref="display"/>
</bean>
<!-- no:完全手動 -->
<bean id="computer6" class="com.redoffice.Computer" autowire="no">
<constructor-arg index="0" ref="host"/>
<constructor-arg index="1" ref="display"/>
</bean>
</beans>
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Computer c1 = (Computer) ac.getBean("computer1"); // byName
Computer c2 = (Computer) ac.getBean("computer2"); // byType
Computer c3 = (Computer) ac.getBean("computer3"); // default(autodetect→constructor)
Computer c4 = (Computer) ac.getBean("computer4"); // autodetect→constructor
Computer c5 = (Computer) ac.getBean("computer5"); // constructor
Computer c6 = (Computer) ac.getBean("computer6"); // no (手動)
c1.run(); c2.run(); ... // 均輸出:主機運行中, 顯示器運行中
autodetect/default:隱式行為導致構造器變更時靜默切換策略,極難排查constructor 注入:保證對象創建即完整、不可變、易測試(無需 setter)@Primary / @Qualifier:多實現場景消除歧義@Autowired:構造器注入成為默認default-autowire 慎用:建議顯式在每個 <bean> 聲明,配置即文檔XML 時代的 autowire 屬性已基本被 @Autowired、@Inject、@Resource 取代:
| 注解 | 來源 | 匹配規則 | 推薦度 |
|---|---|---|---|
@Autowired | Spring | byType → byName(配合 @Qualifier) | ⭐⭐⭐⭐⭐ |
@Resource | JSR-250 | byName → byType | ⭐⭐⭐⭐ |
@Inject | JSR-330 | byType | ⭐⭐⭐ |
理解五大自動裝配模式本質是「屬性名/類型 → Bean 定義」的匹配策略。現代 Spring 開發強烈建議:構造器注入 + @Autowired(單構造器可省略)+ 顯式 @Qualifier 消除歧義,完全拋棄 XML autowire 屬性,擁抱類型安全、重構友好的注解驅動時代。