目录
2. 若有多个类型匹配的 Bean,自动转换为 byName 的方式
3. 若 byType 和 byName 都无法实现自动装配
四、知识总结表格---精华
一、@Autowired
注解能够标识的位置
1. 标识在成员变量上
-
示例代码:
@Controller
public class UserController {
@Autowired
private UserService userService; // 直接注入到成员变量
public void doSomething() {
userService.performAction();
}
}
- 测试代码:
@Test
public void testAutowiredOnField() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.class);
userController.doSomething();
}
- 测试输出:
UserService: performAction executed.
-
输出结果分析:
-
@Autowired
直接注入到成员变量userService
,Spring 容器通过类型匹配找到UserService
的实现类并注入。 -
调用
doSomething()
方法时,userService.performAction()
正常执行。
-
2. 标识在 set
方法上
-
示例代码:
@Controller
public class UserController {
private UserService userService;
@Autowired
public void setUserService(UserService userService) { // 通过 set 方法注入
this.userService = userService;
}
public void doSomething() {
userService.performAction();
}
}
- 测试代码:
@Test
public void testAutowiredOnSetter() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.class);
userController.doSomething();
}
- 测试输出:
UserService: performAction executed.
-
输出结果分析:
-
@Autowired
注解在setUserService
方法上,Spring 容器通过类型匹配找到UserService
的实现类并调用setUserService
方法注入。 -
调用
doSomething()
方法时,userService.performAction()
正常执行。
-
3. 标识在为当前成员变量赋值的有参构造器上
-
示例代码:
@Controller
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) { // 通过构造器注入
this.userService = userService;
}
public void doSomething() {
userService.performAction();
}
}
- 测试代码:
@Test
public void testAutowiredOnConstructor() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.class);
userController.doSomething();
}
- 测试输出:
UserService: performAction executed.
-
输出结果分析:
-
@Autowired
注解在构造器上,Spring 容器通过类型匹配找到UserService
的实现类并通过构造器注入。 -
调用
doSomething()
方法时,userService.performAction()
正常执行。
-
二、@Autowired
的原理
1. 默认通过 byType
的方式
-
示例代码:
@Service
public class UserServiceImpl implements UserService {
@Override
public void performAction() {
System.out.println("UserService: performAction executed.");
}
}
@Controller
public class UserController {
@Autowired
private UserService userService; // 根据类型 UserService 匹配 UserServiceImpl
public void doSomething() {
userService.performAction();
}
}
- 测试代码:
@Test
public void testAutowiredByType() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.class);
userController.doSomething();
}
- 测试输出:
UserService: performAction executed.
-
输出结果分析:
-
Spring 容器通过
byType
的方式找到UserService
的实现类UserServiceImpl
并注入。 -
调用
doSomething()
方法时,userService.performAction()
正常执行。
-
2. 若有多个类型匹配的 Bean,自动转换为 byName
的方式
-
示例代码:
@Service("userServiceA")
public class UserServiceImplA implements UserService {
@Override
public void performAction() {
System.out.println("UserServiceA: performAction executed.");
}
}
@Service("userServiceB")
public class UserServiceImplB implements UserService {
@Override
public void performAction() {
System.out.println("UserServiceB: performAction executed.");
}
}
@Controller
public class UserController {
@Autowired
private UserService userServiceA; // 根据名称 userServiceA 匹配 UserServiceImplA
public void doSomething() {
userServiceA.performAction();
}
}
- 测试代码:
@Test
public void testAutowiredByName() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.class);
userController.doSomething();
}
- 测试输出:
UserServiceA: performAction executed.
-
输出结果分析:
-
Spring 容器通过
byName
的方式找到userServiceA
并注入。 -
调用
doSomething()
方法时,userServiceA.performAction()
正常执行。
-
3. 若 byType
和 byName
都无法实现自动装配
-
示例代码:
@Service
public class UserServiceImplA implements UserService {
@Override
public void performAction() {
System.out.println("UserServiceA: performAction executed.");
}
}
@Service
public class UserServiceImplB implements UserService {
@Override
public void performAction() {
System.out.println("UserServiceB: performAction executed.");
}
}
@Controller
public class UserController {
@Autowired
private UserService userService; // 抛出 NoUniqueBeanDefinitionException
}
- 测试代码:
@Test(expected = NoUniqueBeanDefinitionException.class)
public void testAutowiredNoUniqueBean() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.class);
userController.doSomething();
}
- 测试输出:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'UserService' available: expected single matching bean but found 2: userServiceImplA,userServiceImplB
-
输出结果分析:
-
Spring 容器中有多个
UserService
的实现类,且未指定具体注入哪个 Bean,因此抛出NoUniqueBeanDefinitionException
。
-
4. 使用 @Qualifier
指定 Bean 的 id
-
示例代码:
@Controller
public class UserController {
@Autowired
@Qualifier("userServiceA") // 指定注入 userServiceA
private UserService userService;
public void doSomething() {
userService.performAction();
}
}
- 测试代码:
@Test
public void testAutowiredWithQualifier() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.class);
userController.doSomething();
}
- 测试输出:
UserServiceA: performAction executed.
-
输出结果分析:
-
通过
@Qualifier
指定注入userServiceA
,Spring 容器成功注入并调用performAction()
方法。
-
三、@Autowired
的注意事项
1. 若 IOC 容器中没有任何一个类型匹配的 Bean
-
示例代码:
@Controller
public class UserController {
@Autowired
private NonExistentService nonExistentService; // 抛出 NoSuchBeanDefinitionException
}
- 测试代码:
@Test(expected = NoSuchBeanDefinitionException.class)
public void testAutowiredNoSuchBean() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.class);
userController.doSomething();
}
- 测试输出:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'NonExistentService' available
-
输出结果分析:
-
Spring 容器中未找到
NonExistentService
的实现类,抛出NoSuchBeanDefinitionException
。
-
2. required
属性
-
示例代码:
@Controller
public class UserController {
@Autowired(required = false)
private OptionalService optionalService; // 如果 IOC 容器中没有 OptionalService,则 optionalService 为 null
public void doSomething() {
if (optionalService != null) {
optionalService.performAction();
} else {
System.out.println("optionalService is null.");
}
}
}
- 测试代码:
@Test
public void testAutowiredRequiredFalse() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.class);
userController.doSomething();
}
- 测试输出:
optionalService is null.
-
输出结果分析:
-
由于
required = false
,Spring 容器未找到OptionalService
的实现类时,optionalService
为null
,程序不会抛出异常。
-
四、知识总结表格
场景 | 代码示例 | 测试输出 | 输出结果分析 |
---|---|---|---|
标识在成员变量上 | @Autowired private UserService userService; |
UserService: performAction executed. |
直接注入到成员变量,Spring 通过类型匹配找到 Bean 并注入。 |
标识在 set 方法上 |
@Autowired public void setUserService(UserService userService) {...} |
UserService: performAction executed. |
通过 set 方法注入,Spring 调用 setUserService 方法注入 Bean。 |
标识在构造器上 | @Autowired public UserController(UserService userService) {...} |
UserService: performAction executed. |
通过构造器注入,Spring 调用构造器注入 Bean。 |
默认 byType 注入 |
@Autowired private UserService userService; |
UserService: performAction executed. |
Spring 通过类型匹配找到 Bean 并注入。 |
多个匹配 Bean,byName 注入 |
@Autowired private UserService userServiceA; |
UserServiceA: performAction executed. |
Spring 通过名称匹配找到 Bean 并注入。 |
多个匹配 Bean,未指定名称 | @Autowired private UserService userService; |
NoUniqueBeanDefinitionException |
多个匹配 Bean 未指定名称,抛出异常。 |
使用 @Qualifier 指定 Bean |
@Autowired @Qualifier("userServiceA") private UserService userService; |
UserServiceA: performAction executed. |
通过 @Qualifier 指定 Bean 名称,Spring 注入指定 Bean。 |
无匹配 Bean,抛出异常 | @Autowired private NonExistentService nonExistentService; |
NoSuchBeanDefinitionException |
未找到匹配 Bean,抛出异常。 |
required = false ,未找到 Bean |
@Autowired(required = false) private OptionalService optionalService; |
optionalService is null. |
未找到匹配 Bean,optionalService 为 null ,程序不会抛出异常。 |