依赖注入,英文单词是Dependency Injection,简写为:DI。Spring的依赖注入主要有两种方式:基于XML配置和基于注解的配置。
1. 依赖注入的核心思想
依赖注入是 Spring IoC(控制反转)的核心功能,目的是解耦组件之间的依赖关系。
- 传统方式:对象主动创建或查找依赖(例如 new Service())。
- 依赖注入:由 Spring 容器负责创建对象并注入依赖(例如通过构造器、Setter 方法或注解自动装配)。
2. 依赖注入的三种方式
2.1 构造器注入(推荐方式)
通过构造器参数传递依赖,确保对象在创建时依赖已就绪。
优点:避免空指针,适用于强依赖场景。
方式一:
public class UserService {
private final UserRepository userRepository;
// 构造器注入
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
方式二:XML配置
<bean id="userRepository" class="com.example.UserRepositoryImpl" />
<bean id="userService" class="com.example.UserService">
<constructor-arg ref="userRepository" />
</bean>
方式三:Java配置类
@Configuration
public class AppConfig {
@Bean
public UserRepository userRepository() {
return new UserRepositoryImpl();
}
@Bean
public UserService userService(UserRepository userRepository) {
return new UserService(userRepository);
}
}
2.2 Setter方法注入
通过 Setter 方法设置依赖,适用于可选依赖或需要动态更新的场景。
方式一:
public class OrderService {
private PaymentService paymentService;
// Setter 注入
public void setPaymentService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
方式二:XML配置
<bean id="paymentService" class="com.example.PaymentServiceImpl" />
<bean id="orderService" class="com.example.OrderService">
<property name="paymentService" ref="paymentService" />
</bean>
2.3 注解自动装配
通过 @Autowired 注解自动注入依赖(推荐结合组件扫描使用)
@Service
public class ProductService {
private final InventoryRepository inventoryRepository;
// 构造器注入(可省略 @Autowired)
@Autowired
public ProductService(InventoryRepository inventoryRepository) {
this.inventoryRepository = inventoryRepository;
}
}
@Repository
public class InventoryRepositoryImpl implements InventoryRepository {
// 实现类
}
启用组件扫描:
<!-- XML 方式 -->
<context:component-scan base-package="com.example" />
或通过 Java 配置类
@Configuration
@ComponentScan("com.example")
public class AppConfig {}
3. 常用注解
注解 | 说明 |
---|---|
@Autowired | 自动装配依赖(默认按类型匹配,可结合 @Qualifier 按名称匹配) |
@Qualifier | 指定具体的 Bean 名称(解决同一接口多个实现类的歧义) |
@Primary | 标记为首选 Bean(当存在多个同类型 Bean 时优先注入) |
@Component | 通用组件注解,标记为 Spring 管理的 Bean |
@Service | 标记业务层组件(语义化注解,本质是 @Component) |
@Repository | 标记数据访问层组件(自动处理数据库异常) |
@Configuration | 标记配置类,定义 Bean |
@Bean | 在配置类中声明 Bean(适用于第三方库的集成) |
4. 解决依赖冲突
当同一接口有多个实现时,需明确指定注入的 Bean:
@Service
public class PaymentService {
private final PaymentGateway paymentGateway;
@Autowired
public PaymentService(@Qualifier("paypalGateway") PaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}
}
配置多个实现类:
@Configuration
public class PaymentConfig {
@Bean
public PaymentGateway paypalGateway() {
return new PaypalGateway();
}
@Bean
public PaymentGateway stripeGateway() {
return new StripeGateway();
}
}