1. 概述
在 Spring 的 XML 配置中,<context:annotation-config>
和 <context:component-scan>
是两个非常常见的配置标签。它们都与注解的使用有关,但作用范围和机制有明显差异。
本文将从实际开发角度出发,分析这两个标签的区别,并通过示例代码帮助你理解它们的适用场景。
2. Bean 定义方式
Spring 提供了两种定义 Bean 的方式:
- XML 配置文件
- Java 注解(annotations)
Spring 的注解又可分为两大类:
- Bean 定义注解:如
@Component
、@Service
、@Repository
、@Controller
等,用于标识某个类为 Spring 管理的 Bean。 - 依赖注入注解:如
@Autowired
、@Qualifier
、@Resource
、@PostConstruct
、@PreDestroy
等,用于自动装配依赖。
在使用这些注解前,必须显式激活它们,否则 Spring 不会自动识别这些注解。
这就引出了我们今天的两个主角:
✅ <context:annotation-config>
:激活已注册 Bean 中的依赖注入注解
✅ <context:component-scan>
:不仅激活依赖注入注解,还能自动扫描并注册 Bean 定义注解
接下来我们分别看它们的作用。
3. 使用 <context:annotation-config>
激活注解
<context:annotation-config>
的主要作用是激活已经注册的 Bean 中的依赖注入注解,比如:
@Autowired
@Resource
@Qualifier
@PostConstruct
@PreDestroy
⚠️ 它不会自动扫描类路径下带有 @Component
等注解的类。
示例代码
public class UserService {
@Autowired
private AccountService accountService;
}
public class AccountService {}
对应的 XML 配置如下:
<bean id="accountService" class="AccountService" />
<bean id="userService" class="UserService" />
此时,如果你没有在 XML 中添加 <context:annotation-config/>
,即使你用了 @Autowired
,Spring 也不会自动注入 accountService
。
添加后:
<context:annotation-config/>
这样 Spring 才会识别 @Autowired
注解并完成自动注入。
踩坑提醒 ⚠️
很多人以为加了 @Autowired
就万事大吉,其实不然。如果你没激活注解,Spring 是不会处理这些注解的!
4. 使用 <context:component-scan>
自动扫描和激活注解
<context:component-scan>
的功能更强大,它不仅会激活依赖注入注解,还会自动扫描指定包下的类,并根据注解(如 @Component
、@Service
等)自动注册为 Spring Bean。
也就是说,它做了两件事:
- 自动扫描并注册 Bean
- 激活依赖注入注解
支持的注解包括:
@Component
@Service
@Repository
@Controller
@RestController
@Configuration
示例代码
@Component
public class UserService {
@Autowired
private AccountService accountService;
}
@Component
public class AccountService {}
XML 配置只需一行:
<context:component-scan base-package="com.example.annotationdemo" />
这样 Spring 会自动扫描 com.example.annotationdemo
包下的类,并注册为 Bean,同时处理 @Autowired
等注解。
踩坑提醒 ⚠️
如果你只用了 @Component
但没配置 <context:component-scan>
,Spring 是不会注册这些类为 Bean 的!
5. 两者区别总结
功能 | <context:annotation-config> |
<context:component-scan> |
---|---|---|
激活依赖注入注解(如 @Autowired ) |
✅ | ✅ |
自动扫描并注册 Bean(如 @Component ) |
❌ | ✅ |
是否需要手动定义 Bean | ✅ | ❌ |
是否需要指定包路径 | ❌ | ✅ |
适用场景 | 已使用 XML 定义 Bean,但想用注解做依赖注入 | 想用注解定义 Bean 和依赖注入 |
6. 结论
简单粗暴地说:
- 如果你已经在 XML 中手动定义了所有 Bean,但想使用
@Autowired
做依赖注入,就用<context:annotation-config>
- 如果你想用
@Component
、@Service
等注解自动注册 Bean,同时使用@Autowired
做依赖注入,那就用<context:component-scan>
两者可以共存,但通常 <context:component-scan>
已经包含了 <context:annotation-config>
的功能,所以大多数项目只需配置它即可。