核心配置:開啟組件掃描
<!-- applicationContext.xml -->
<context:component-scan base-package="com.example.service, com.example.dao" />
base-package:多包用逗號/分號/空格分隔,掃描該包及子包下所有帶註解的類。
- 需引入
context 命名空間:xmlns:context="https://www.springframework.org/schema/context"。
四大核心註解語義區分
| 註解 | 語義層級 | 典型用途 | 特殊功能 |
@Component | 通用組件 | 不屬於特定層的工具類、工廠類 | 元註解,其他三個繼承它 |
@Repository | 持久層 (DAO) | DataAccessException 自動轉換、AOP 切面增強 | 持久層異常翻譯 |
@Service | 業務邏輯層 | 事務邊界 @Transactional、業務邏輯封裝 | 標識業務核心 |
@Controller | 表現層 (Spring MVC) | 請求映射 @RequestMapping、視圖解析 | Web 層標識 |
💡 本質上四者都是 @Component,Spring 通過類名掃描識別,語義區分便於 AOP 切點表達式精準匹配 (如 execution(* com.example.service.*.*(..)))。
實戰代碼示例
DAO 層
@Repository("commodityDao") // 指定 Bean 名稱,默認類名首字母小寫 commodityDaoImpl
public class CommodityDaoImpl implements CommodityDao {
@Autowired private JdbcTemplate jdbcTemplate; // 注入模板
// CRUD 方法...
}
Service 層
@Service("commodityService")
public class CommodityServiceImpl implements CommodityService {
@Autowired private CommodityDao commodityDao; // 按類型注入
// 業務方法...
}
Controller 層 (Spring MVC)
@Controller
@RequestMapping("/commodity")
public class CommodityController {
@Autowired private CommodityService commodityService;
@GetMapping("/list")
public String list(Model model) {
model.addAttribute("list", commodityService.findAll());
return "commodity/list"; // 視圖名
}
}
進階配置技巧
- 排除/包含過濾器:
<context:component-scan base-package="com.example">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="regex" expression="com.example.ignore.*"/>
</context:component-scan>
- 自定義註解掃描:元註解
@Component 定義業務註解 @MyService,掃描器識別同樣生效。
- 屬性占位符:
<context:property-placeholder location="classpath:jdbc.properties"/> 解析 ${jdbc.url}。
Spring Boot 時代的簡化 (對比參考)
@SpringBootApplication // 等價於 @Configuration + @EnableAutoConfiguration + @ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// 無需 XML,主類所在包及子包自動掃描,application.yml 替代 properties/xml
常見錯誤與排查
| 現象 | 原因 | 解決 |
| Bean 未注入 (NoSuchBeanDefinitionException) | 包路徑不在掃描範圍、註解拼寫錯誤、類未被編譯 | 檢查 base-package、重新編譯、啟動日志搜索 "Scanning" |
| 循環依賴 | 字段注入 + 無 @Lazy、構造器注入循環 | 改構造器注入、引入 @Lazy、重構拆分服務 |
| 重複 Bean 定義 | XML 又聲明、掃描重複、同名 Bean | 統一配置方式、指定唯一 name/value |