Autowired自动装配
@Autowired 的自动装配模式
@Autowired 默认是 按类型 (byType) 自动注入的。
按类型注入
按类型注入指的是:当 Spring 发现当前字段有 @Autowired 的标注之后,会去查看其字段类型,然后去寻找已注册的实现了当前字段类型的 Bean 然后初始化注入。
@Autowired
private UserService userService;
// 当前字段类型为 UserService
// UserService.java
public interface UserService { ... }
// UserServiceImpl.java
@Service
public class UserServiceImpl implements UserService { ... }
在上面例子中,已注册的实现 UserService 的 Bean 是 UserServiceImpl,Spring 会把这个 Bean 实例化注入到 userService 中。
当有多个同类型 Bean 时会怎样,如何解决?
在上面的例子中如果我们同时实现了多个 UserService 的话会怎样?
@Autowired
private UserService userService;
// UserService.java
public interface UserService { ... }
// UserServiceImpl.java
@Service
public class UserServiceImpl implements UserService { ... }
// UserServiceImpl2.java
@Service
public class UserServiceImpl2 implements UserService { ... }
这种情况会抛出 NoUniqueBeanDefinitionException 错误。
解决方案:@Qualifier 显式指定
可以使用 @Qualifier 注解指定具体的 Bean 名称,从而在多个同类型 Bean 中精确选择一个进行注入。
@Qualifier("userServiceImpl") // 注意:默认 bean 名称为类名首字母小写
@Autowired
private UserService userService;
@Service 注解默认生成的 Bean 名称是类名的首字母小写(如 UserServiceImpl → userServiceImpl)
解决方案:@Primary 标记首选
@Service
@Primary
public class UserServiceImpl implements UserService { ... }
标记了 @Primary 的 Bean 会在多个候选 Bean 中被优先选择。
@Autowired 的注入位置
1. 字段注入
@Autowired
private UserService userService;
- 简洁直接
- 不支持 final 字段
- 不利于单元测试
2. Setter 注入
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
- 可选依赖
- 不支持 final 字段
3. 构造器注入(推荐)
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
从 Spring 4.3 开始,如果类只有一个构造器,@Autowired 可以省略。
优点:
- 支持 final 字段,保证不可变性
- 依赖关系清晰,便于理解
- 便于单元测试(可以直接 new 对象)
- 配合 Lombok 的
@RequiredArgsConstructor更简洁