從 XML 走向註解,是 Spring 簡化配置、提升開發效率的關鍵里程碑。本文以 MVC 三層架構為例,展示如何使用掃描註解(`
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="...>
<!-- 掃描基礎包及子包下所有類,自動註冊帶有 @Component 衍生註解的類為 Bean -->
<context:component-scan base-package="com.lee.spring012.scan.mvc.annotation"/>
</beans>
掃描機制:容器啟動時遞迴掃描 `base-package` 下所有 `.class` 檔案,檢測類上是否標註 `@Component`、`@Controller`、`@Service`、`@Repository`、`@Configuration` 等,若有則自動註冊為 Bean,Bean 名稱預設為類名首字母小寫(如 `PersonAction` → `personAction`)。
| 註解 | 目標層 | 語義 | 額外功能 |
|---|---|---|---|
@Controller | 表現層 | 接收請求、返回視圖/JSON | Spring MVC 請求映射支援 |
@Service | 業務層 | 核心業務邏輯、事務邊界 | @Transactional 隱含支援 |
@Repository | 資料層 | DAO、資料庫操作 | 自動將 JDBC/Hibernate 異常轉為 Spring DataAccessException |
@Component | 通用 | 不屬於上述三層的元件 | 基礎掃描標識 |
四者本質上都是 `@Component` 的特化,使用語義註解能讓架構意圖一目了然,並啟用層專屬功能。
// Action 層
@Controller
@Scope("prototype") // Action 多例,避免狀態共享
public class PersonAction {
@Resource // 預設按名稱注入:尋找名為 "stuServiceImpl" 的 Bean
public IStuService stuServiceImpl;
public void displaySave() {
System.out.println("mvc action: saving stu...");
stuServiceImpl.saveStu();
}
}
// Service 層
@Service
public class StuServiceImpl implements IStuService {
@Resource
public IStuDAO stuDAOImpl;
@Override
public void saveStu() {
System.out.println("mvc service: saving stu...");
stuDAOImpl.saveStu();
}
}
// DAO 層
@Repository
public class StuDAOImpl implements IStuDAO {
@Override
public void saveStu() {
System.out.println("mvc dao: saving stu...");
}
}
@Resource vs @Autowired 關鍵差異:
Spring Bean 預設為單例。Controller/Action 處理請求時若有實例變數(如表單綁定物件),單例會導致併發下狀態汙染。標註 `@Scope("prototype")` 確保每次 `getBean`/注入都創建新實例。
@Test
public void testPersonAction() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-scan-mvc.xml");
PersonAction person = (PersonAction) context.getBean("personAction"); // 預設名稱 personAction
person.displaySave();
}
mvc action: saving stu...
mvc service: saving stu...
mvc dao: saving stu...
@Configuration
@ComponentScan("com.lee.spring012.scan.mvc.annotation")
public class AppConfig {
// 無需任何 XML,main 方法直接啟動:
// new AnnotationConfigApplicationContext(AppConfig.class);
}
https://github.com/leechenxiang/maven-spring001-helloworld
註解驅動開發將 Bean 定義從 XML 釋放,回到 Java 類內部,實現配置與代碼共生。掌握 `