下面分别用三种配置方式实现一个简单示例:UserService
依赖 UserRepository
,Spring容器将自动注入依赖。
1. XML 配置方式
<!-- applicationContext.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 显式声明每个Bean -->
<bean id="userRepository" class="com.example.UserRepositoryImpl"/>
<bean id="userService" class="com.example.UserService">
<!-- 通过Setter方法注入依赖 -->
<property name="userRepository" ref="userRepository"/>
</bean>
</beans>
// UserRepository 接口
public interface UserRepository {
String getUser();
}
// UserRepository 实现类
public class UserRepositoryImpl implements UserRepository {
@Override
public String getUser() {
return "User from Repository";
}
}
// UserService 类
public class UserService {
private UserRepository userRepository;
// Setter 方法用于依赖注入
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
public String getUser() {
return userRepository.getUser();
}
}
启动容器:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService.getUser()); // 输出: User from Repository
ps:
context.getBean方法中,
参数1:表示Bean在XML中定义的唯一标识符(ID)。
参数2:表示指定返回对象的类型,Spring会检查该Bean是否可安全转换为指定类型(避免强制类型转换)
有.class和没有.class的区别:
没有 .class 参数的版本返回的是 Object 类型:
UserService userService = (UserService) context.getBean(“userService”); // 需要强制转换
使用 .class 参数后:
UserService userService = context.getBean(“userService”, UserService.class); // 自动类型转换
相当于编译器帮你完成了类型转换,代码更简洁安全
2. 注解 + 组件扫描
// 启用组件扫描(指定包路径)
@Configuration
@ComponentScan("com.example")
public class AppConfig {
}
// 标记为Repository(Spring会自动注册为Bean)
@Repository
public class UserRepositoryImpl implements UserRepository {
@Override
public String getUser() {
return "User from Repository";
}
}
// 标记为Service,并通过@Autowired自动注入依赖
@Service
public class UserService {
private final UserRepository userRepository;
// 构造器注入
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public String getUser() {
return userRepository.getUser();
}
}
启动容器:
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean(UserService.class);
System.out.println(userService.getUser()); // 输出: User from Repository
ps:
通过Bean的类型直接获取实例。要求容器中必须存在且仅有一个该类型的Bean.适用于使用注解(如@Service)标记的类:
3. Java 配置类(@Configuration + @Bean)
@Configuration
public class AppConfig {
// 手动创建并返回Bean(方法名即默认Bean ID)
@Bean
public UserRepository userRepository() {
return new UserRepositoryImpl();
}
// 注入依赖:直接调用userRepository()方法(Spring会拦截并返回单例)
@Bean
public UserService userService(UserRepository userRepository) {
return new UserService(userRepository);
}
}
// 此处无需注解(由配置类管理Bean)
public class UserRepositoryImpl implements UserRepository {
@Override
public String getUser() {
return "User from Repository";
}
}
// 此处无需注解
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public String getUser() {
return userRepository.getUser();
}
}
启动容器:
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService.getUser()); // 输出: User from Repository
ps:
context.getBean方法中,
参数1:表示对应配置类中@Bean方法定义的名称。
参数2:表示指定返回对象的类型,Spring会检查该Bean是否可安全转换为指定类型(避免强制类型转换)
三种方式对比
配置方式 | 优点 | 缺点 |
---|---|---|
XML | 集中管理、与代码解耦 | 冗长、类型不安全、调试困难 |
注解 + 组件扫描 | 简洁、开发效率高 | 依赖分散在代码中 |
Java配置类(@Bean) | 纯Java代码、类型安全、灵活控制逻辑 | 需手动编写Bean定义 |
现代Spring开发趋势:
- Spring Boot 默认使用注解 + 组件扫描
(如@Service
/@Autowired
)。
- 需要精细控制Bean时(如集成第三方库),配合Java配置类
(@Bean
)。
- XML配置 逐渐被替代,仅用于遗留系统维护。