依赖注入 - 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 官方更推荐 常见但略逊于构造函数注入
相关推荐
深蓝AI10 分钟前
Gemini Decisions API 来了:一次前向打分取代逐字解码,校准误差 0.0250 才是 agent 分支调用的真门槛
人工智能·后端
学长毕设30 分钟前
基于SpringBoot公务员考试交流平台-附源码
java·spring boot·后端
IT_陈寒1 小时前
Vue的watch把我坑惨了,原来要这样用才靠谱
前端·人工智能·后端
黃芢輝2 小时前
开源实战:基于 Spring Boot 3 + Vue 3 + Redis 的高校选修课管理系统(志愿填报 + 统一抽签)
后端
小雨的AI中台笔记2 小时前
502 还是 503?「无可用渠道」其实只有三个原因
后端
LCG元2 小时前
我让AI重写了这个老系统
后端
吴汐2 小时前
【CRMEB 社区版】二开第一问:这个需求该进 driver,还是进 modules?
后端
新*2 小时前
Elasticsearch 7.17 的 SQL 到底能查到什么?一次踩坑记录
后端·sql·elasticsearch·查询
卷无止境2 小时前
SALib敏感性分析的python库学习笔记
后端·python
ServBay2 小时前
从 Val Town 停服看,代码能下载不代表项目能搬家
后端·sqlite