疑問:控制台程序用 `new ClassPathXmlApplicationContext()` 獲取 Bean,Service 層用 `@Resource` 直接注入,為何不需要手動創建容器?
| 模式 | 容器創建者 | Bean 獲取方式 | 適用場景 |
|---|---|---|---|
| **手動啟動** | 開發者代碼 (`main` 方法) | `context.getBean()` | 獨立應用、批處理、測試、非 Web 環境 |
| **Web 容器托管** | Servlet 容器 (Tomcat/Jetty) 啟動時 | 依賴注入 (`@Autowired`/`@Resource`) | Spring MVC、Spring Boot Web 應用 |
1. Tomcat 啟動
↓
2. 讀取 web.xml → 發現 ContextLoaderListener
↓
3. Listener.contextInitialized() →
new XmlWebApplicationContext() →
載入 applicationContext.xml →
實例化所有 (含 hibernateTemplate)
↓
4. 將容器存入 ServletContext 屬性 "org.springframework.web.context.WebApplicationContext.ROOT"
↓
5. DispatcherServlet 初始化 →
獲取父容器 → 創建子容器 (掃描 @Controller)
↓
6. 掃描 @Service/@Repository/@Component →
自動裝配 @Resource hibernateTemplate →
注入到 Service 字段
↓
7. 請求到達 → Controller → Service.method() → 直接使用 hibernateTemplate
public class Main {
public static void main(String[] args) {
// 1. 手動創建容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2. 手動獲取
HibernateTemplate ht = ctx.getBean("hibernateTemplate", HibernateTemplate.class);
// 3. 使用
ht.save(new User("test"));
// 4. 關閉容器 (非 Web 必須)
((ConfigurableApplicationContext)ctx).close();
}
}
@Service
public class UserService {
// 容器已在 Tomcat 啟動時創建完畢
// @Resource 按名稱匹配
@Resource(name = "hibernateTemplate")
private HibernateTemplate ht; // 自動注入,無需手動獲取
public void save(User u) { ht.save(u); }
}
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.example.entity"/>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 掃描 Service 自動裝配 -->
<context:component-scan base-package="com.example.service" />