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。

也就是说,它做了两件事:

  1. 自动扫描并注册 Bean
  2. 激活依赖注入注解

支持的注解包括:

  • @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> 的功能,所以大多数项目只需配置它即可。


原始标题:Difference between vs | Baeldung