2025/2/29 下午《尚硅谷》——spring---基于注解的自动装配之@Autowire(代码示例详解)

目录

一、@Autowired 注解能够标识的位置

1. 标识在成员变量上

2. 标识在 set 方法上

3. 标识在为当前成员变量赋值的有参构造器上

二、@Autowired 的原理

1. 默认通过 byType 的方式

2. 若有多个类型匹配的 Bean,自动转换为 byName 的方式

3. 若 byType 和 byName 都无法实现自动装配

4. 使用 @Qualifier 指定 Bean 的 id

三、@Autowired 的注意事项

1. 若 IOC 容器中没有任何一个类型匹配的 Bean

2. required 属性

四、知识总结表格---精华


一、@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,程序不会抛出异常。