依賴注入 (DI) 容器演進:Spring (XML 宣告式) → Guice (程式碼內嵌式)。兩者核心差異在於「設定外部化」vs「設定程式碼化」。本文從實作範例、核心特性對比、隱喻說明三個維度深度剖析。
public interface MyService { void myMethod(); }
public class MyServiceImpl implements MyService {
public void myMethod() { System.out.println("Hello, World!"); }
}
import com.google.inject.Inject;
public class Client {
@Inject MyService service; // 欄位直接注入
public void myMethod() { service.myMethod(); }
}
import com.google.inject.*;
public class MyModule implements Module {
public void configure(Binder binder) {
binder.bind(MyService.class)
.to(MyServiceImpl.class)
.in(Scopes.SINGLETON); // 單例範圍
}
}
import com.google.inject.*;
public class Test {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new MyModule());
Client client = new Client();
injector.injectMembers(client); // 對已建立物件注入
client.myMethod(); // 輸出: Hello, World!
}
}
@ImplementedBy(MyServiceImpl.class)
public interface MyService { void myMethod(); }
Module 中無需重複綁定,Guice 自動解析。
@Inject public Client(MyService s) { this.service = s; }@Inject public void setService(MyService s) { }@Inject MyService service;
// 定義限定註解
@Retention(RUNTIME) @Target({FIELD, PARAMETER}) @BindingAnnotation
public @interface MyInterface {}
// 客戶端使用
@Inject @MyInterface MyService service;
// Module 綁定
binder.bind(MyService.class)
.annotatedWith(MyInterface.class)
.to(MyServiceImpl.class)
.in(Scopes.SINGLETON);
| 維度 | Spring | Guice |
|---|---|---|
| 設定方式 | XML 為主,輔以註解 | 純 Java 程式碼 (Module) |
| 綁定定位 | XML 中聲明類關係 | Module 程式碼中聲明 |
| 注解支援 | 完善 (@Autowired, @Component...) | 核心 (@Inject, @ImplementedBy, 自訂 BindingAnnotation) |
| 啟動效能 | 解析 XML、反射掃描,較慢 | 程式碼直執行、cglib 增強,極快 |
| 注入時機 | 容器啟動階段完整注入 (Eager) | 使用時即時注入 |
| 類別侵入性 | 低 (非侵入,POJO 純淨) | 高 (@Inject 滲透業務碼) |
| 功能範疇 | 全棧 (IOC, AOP, ORM, MVC, Security, Batch...) | 專注 DI、AOP、Servlet 擴充 |
| 動態綁定 | 困難 (XML 靜態) | 原生支援 (運行時邏輯決定實作) |
| 生態整合 | 極豐富 (Hibernate, Struts, JPA, Cloud...) | 基礎 (Struts 2, Servlet, JMX) |
| 重構友善度 | XML 需同步修改 | IDE 完美支援重構 |
| 學習曲線 | 平緩 | 陡峭 (需泛型、註解、Module 模式) |
new Dep(),高耦合、難維護| 選擇 Spring 當... | 選擇 Guice 當... |
|---|---|
| 需要完整企業級全棧框架 | 專案輕量、啟動速度關鍵 |
| 團隊習慣 XML 設定、非 Java 配置人員參與 | 偏好程式碼即設定、享受 IDE 重構 |
| 需整合 Hibernate、JPA、Spring Security 等生態 | 需要動態/條件式綁定邏輯 |
| 既有 Spring 技術債、遷移成本高 | 微服務、獨立模組、新專案技術選型自由 |
| 非侵入性 POJO 為核心架構原則 | 接受 @Inject 侵入換取型別安全與速度 |
Guice 不是 Spring 的替代品,而是 DI 風格的另一種極致表達。Spring 贏在生態系完整度與非侵入哲學;Guice 贏在啟動速度、型別安全、重構友善與動態綁定彈性。無絕對優劣,唯有「適合專案情境、團隊能力、長期演進」的選擇。