在 Spring 應用開發中,如何從非 Spring 管理的程式碼(如舊系統整合、工具類、第三方庫回呼)獲取容器管理的 Bean,是常見且關鍵的問題。本文系統整理五種標準獲取策略,涵蓋獨立應用、Web 環境、繼承體系、感知介面四大場景,並說明適用條件與最佳實踐。
ApplicationContext 是 Spring 容器核心介面,提供 getBean(name)、getBean(type)、getBeansOfType(type) 等查詢方法。所有獲取 Bean 的本質,都是先拿到 ApplicationContext(或 WebApplicationContext)參考。
// 載入檔案系統路徑配置
ApplicationContext ctx = new FileSystemXmlApplicationContext("config/applicationContext.xml");
// 或載入類路徑配置
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 獲取 Bean
MyService service = ctx.getBean("myService", MyService.class);
適用:無 Servlet 容器的獨立 JVM 程式(main 方法、批次作業、單元測試不使用 @ContextConfiguration 時)。
缺點:每次呼叫會重新啟動容器,極度低效,**嚴禁在長期運行程式中重複建立**。
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.ServletContext;
// 在 ServletContext 可取得處(Servlet.init、Filter.doFilter、Listener.contextInitialized)
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
// 或允許 null
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
MyService service = wac.getBean(MyService.class);
適用:傳統 web.xml 配置的 Spring MVC 專案、需在 Servlet/Filter/Listener 中獲取 Bean。
關鍵:需持有 ServletContext 參考,通常從 ServletConfig.getServletContext() 或 HttpSession.getServletContext() 取得。
public class MyHelper extends ApplicationObjectSupport {
public void doWork() {
ApplicationContext ctx = getApplicationContext(); // 受保護方法
MyService service = ctx.getBean(MyService.class);
service.execute();
}
}
機制:Spring 容器啟動時,會自動呼叫 setApplicationContext() 將容器注入此基類。
適用:需容器感知的工具類、協助類,且願意繼承 Spring 基類(耦合 Spring API)。
public class MyWebHelper extends WebApplicationObjectSupport {
public void doWork() {
WebApplicationContext wac = getWebApplicationContext();
MyService service = wac.getBean(MyService.class);
}
}
差異:提供 getWebApplicationContext() 直接回傳 Web 專用上下文,可存取 ServletContext 等 Web 資源。
@Component // 或在 XML 定義 bean
public class MyBeanHolder implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
context = applicationContext;
}
public static T getBean(Class type) {
return context.getBean(type);
}
public static T getBean(String name, Class type) {
return context.getBean(name, type);
}
}
機制:Spring 掃描到實作 ApplicationContextAware 的 Bean,自動回呼 setApplicationContext() 注入容器。
優點:不強制繼承基類、靜態方法方便全域呼叫、符合依賴倒置原則。
注意:靜態持有容器參考需確保單例 Bean、容器啟動完成後才呼叫,避免循環依賴或空指標。
getApplicationContext()。| 場景 | 推薦方式 | 關鍵限制 |
|---|---|---|
| 獨立 JVM 程式(main/批次/測試) | 方式一(僅啟動一次) | 勿重複建立容器 |
| 傳統 Web 專案 Servlet/Filter | 方式二 | 需 ServletContext |
| 工具類、第三方庫回呼 | 方式五(ApplicationContextAware) | 需為 Spring Bean、啟動後可用 |
| Spring Boot 專案任意 Bean 內部 | @Autowired ApplicationContext | 最簡潔、類型安全 |