Bean 的注册:XML、注解与 JavaConfig 装配
引言
要让容器“认识”一个类并管理它,必须先把它注册成 Bean。Spring 历史上先后演化出三种注册方式:XML、组件扫描注解、JavaConfig。它们解决同一个问题——告诉容器“有哪些对象、怎么创建”,只是写法不同。本章三种方式各给一个最小示例并说明混用规则。
核心概念
- XML 方式:在配置文件中用
<bean id="..." class="...">声明,一个<bean>对应一个 Bean;另可用<context:component-scan>扫描注解。 - 注解方式:在类上标注
@Component及其语义化子注解(@Service、@Repository、@Controller、@Configuration),再用@ComponentScan指定扫描包路径。 - JavaConfig 方式:
@Configuration类中用@Bean方法声明 Bean,方法返回值即 Bean 实例,方法名默认即 Bean 名称;适合注册第三方类或构造逻辑复杂的 Bean。 - 三者都注册进同一个容器,可共存:XML 声明 + 扫描注解 +
@Bean混用是允许的,同名冲突时以注册先后/覆盖规则为准(以官方文档为准)。
代码示例
// 方式一:XML(classpath:beans.xml)
// <beans ...> 需声明 beans 命名空间(具体 schema 位置以官方文档为准,此处从略)
// <bean id="greetingService"
// class="com.example.GreetingService"/>
// </beans>
// 容器:new ClassPathXmlApplicationContext("beans.xml")
// 方式二:组件扫描注解
@Service
public class GreetingService {
public String greet(String who) { return "Hello, " + who; }
}
@Configuration
@ComponentScan("com.example") // 扫描 com.example 下的 @Component/@Service/...
public class AppConfig { }
// 方式三:JavaConfig 显式 @Bean
@Configuration
public class AppConfig2 {
@Bean
public GreetingService greetingService() {
return new GreetingService(); // 也可以在这里做复杂构造
}
}
// 三种方式统一用容器获取:
try (AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class)) {
GreetingService s = ctx.getBean("greetingService", GreetingService.class);
System.out.println(s.greet("Spring"));
}
注意点
@Component系注解必须配合@ComponentScan(或 Boot 的@SpringBootApplication)才会被扫描到;忘了扫描是新手最常见问题。@Bean方法返回类型决定 Bean 类型;方法所在@Configuration类本身也是个 Bean。- XML 命名空间与 Spring 版本相关,现代项目优先注解/JavaConfig;老项目改造时注意混用陷阱(同名 Bean 覆盖、扫描范围重叠)。
- Bean 名称默认规则:注解为类名首字母小写,
@Bean为方法名;均可用@Service("name")/@Bean("name")显式指定。
小结
三种注册方式解决同一件事:XML 声明式、注解靠扫描、JavaConfig 用 @Bean 方法。推荐组合是“@Component 标业务类 + @ComponentScan 扫描 + @Bean 注册第三方类”,第 04 章将在此基础上讲依赖注入。