依赖注入 - Spring 在 IoC 容器里查找一个 Bean 的不同方式示例

通过写一个完整的 Spring 示例 ,展示同时存在两个实现类时,如何用 @Resource@Qualifier 精确选择注入。

现有代码

  1. 定义接口
java 复制代码
public interface Processor {
    void process();
}
  1. 两个实现类
java 复制代码
import org.springframework.stereotype.Component;

@Component("creditCardProcessor")
public class CreditCardProcessor implements Processor {
    @Override
    public void process() {
        System.out.println("Processing credit card...");
    }
}

@Component("zhiFuBaoProcessor")
public class ZhiFuBaoProcessor implements Processor {
    @Override
    public void process() {
        System.out.println("Processing zhifubao...");
    }
}

第一种:使用 @Resource 指定注入(最常见)

java 复制代码
import javax.annotation.Resource;
import org.springframework.stereotype.Service;

@Service
public class PaymentService1 {

    // 按名字注入,必须和 Bean 名字一致
    @Resource(name="creditCardProcessor")
    private Processor processor;

    public void pay() {
        processor.process();
    }
}

第二种:使用构造函数注入 + @Qualifier(Spring 官方推荐)

java 复制代码
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class PaymentService2 {
    private final Processor processor;

    // 构造函数注入,指定要注入的 Bean
    public PaymentService2(@Qualifier("creditCardProcessor") Processor processor) {
        this.processor = processor;
    }
    
    public void pay() {
        processor.process();
    }
}

容器里只有一个 Processor 类型的 Bean(比如只有 CreditCardProcessor),Spring 会直接注入它,不需要 @Qualifier

第三种:使用 @Autowired + @Qualifier 指定注入

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class PaymentService3 {

    @Autowired
    @Qualifier("zhiFuBaoProcessor")
    private Processor processor;

    public void pay() {
        processor.process();
    }
}

测试运行

java 复制代码
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    CommandLineRunner run(PaymentService1 paymentService1, PaymentService2 paymentService2, PaymentService3 paymentService3) {
        return args -> {
            paymentService1.pay();   // 输出:Processing credit card...
            paymentService2.pay();  // 输出:Processing credit card...
            paymentService3.pay();  // 输出:Processing zhifubao...
        };
    }
}

IoC 的好处

Spring IoC 容器的一个好处:调用方不需要修改,只要容器负责把合适的依赖注入进去

字段注入和构造函数注入的共同点:

  • 解耦调用方 :调用 PaymentService 的地方不需要关心具体用的是 CreditCardProcessor 还是 ZhiFuBaoProcessor
  • 切换实现简单:只要改 Bean 配置或注解,调用代码完全不用动。
  • 由 IoC 容器负责依赖管理:容器在启动时扫描、创建 Bean,并根据注解或配置自动注入。

字段注入和构造函数注入的区别:

特性 构造函数注入 @Resource 字段注入
注入时机 对象创建时必须提供依赖 对象创建后由容器反射赋值
空值风险 无,构造函数强制依赖 有可能出现 null(如果容器没找到匹配 Bean)
测试友好性 更方便单元测试(直接传 mock) 测试时需要容器或反射赋值
推荐程度 Spring 官方更推荐 常见但略逊于构造函数注入
相关推荐
前端工作日常9 小时前
我学习到的Java类和对象区别
java·后端
前端工作日常10 小时前
我学习到的Java类完整结构
java·后端
Csvn10 小时前
📊 SQL 入门 Day 6:多表查询 — JOIN 的四种姿势
后端·sql
hold?fish:palm12 小时前
RDB全量快照备份
c++·redis·后端
LucianaiB12 小时前
我把刘备一生做成了可播放的高德地图,还把整套方法封装成了 Skill
后端
Reart13 小时前
操作系统实验哈工大lab2——系统调用
后端·操作系统
IT_陈寒13 小时前
React useEffect依赖数组中埋的坑,这次终于让我逮到了
前端·人工智能·后端
扎Zn了老Fe13 小时前
MyBatis-Plus必知必会:告别低效CRUD,高效开发持久层
后端·mybatis
用户4603812919413 小时前
终于知道AQS是啥东西了
后端
2501_9185823714 小时前
SwiperController 编程式控制翻页与 showNext
后端