You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中如何注入接口的所有可能实现实例作为构造器依赖?

问题解决:Spring中注入同一实现类的不同实例到工厂类

场景说明

我有如下工厂类:

@Service
class AffectedObjectServiceFactory {

    private static final Map<String, AffectedObjectService> affectedObjectServiceMap = new HashMap<>();
    @Autowired
    private AffectedObjectServiceFactory(List<AffectedObjectService> services) {
        for(AffectedObjectService service : services) {
            String[] supportedSubTypes = service.func1();
            for (String subType: supportedSubTypes) {
                affectedObjectServiceMap.put(subType, service);
            }
        }
    }

    public static AffectedObjectService getAffectedObject(String type) {
        AffectedObjectService affectedObjectService = affectedObjectServiceMap.get(type);
        if(affectedObjectService == null) throw new IllegalArgumentException("Unknown service type: " + type);
        return affectedObjectService;
    }
}

对应的接口及实现类如下:

interface AffectedObjectService {
    String[] func1(); // 修正:与工厂类调用逻辑匹配,返回值应为String[]
}

@Component
class AffectedObjectServiceImpl1 implements AffectedObjectService {
    @Override
    String[] func1() { //.... }
}

@Component
class AffectedObjectServiceImpl2 implements AffectedObjectService {
    @Override
    String[] func1() { //.... }
}

class AffectedObjectServiceImpl3 implements AffectedObjectService {

    XYZInterface type;
    public AffectedObjectServiceImpl3(XYZInterface type) {
        this.type = type;
    }

    @Override
    String[] func1() { //.... }
}

interface XYZInterface {
     String func2();
}

@Component
class XYZInterfaceImpl1 implements XYZInterface { // 修正:接口实现需用implements而非extends
    @Override
    String func2() { // .... }
}

@Component
class XYZInterfaceImpl2 implements XYZInterface {
    @Override
    String func2() { // .... }
}

问题

AffectedObjectService是一个拥有多个实现类的接口,其中部分实现类的构造器依赖其他接口的实现。如何让AffectedObjectServiceImpl3的两个实例(分别依赖XYZInterfaceImpl1和XYZInterfaceImpl2)都作为依赖注入到工厂类的构造器中?


解决方案

核心思路是让Spring显式创建AffectedObjectServiceImpl3的两个实例,分别绑定不同的XYZInterface实现,再将这两个实例纳入List<AffectedObjectService>的注入集合中。推荐采用以下方式:

方式一:通过配置类手动定义Bean

移除AffectedObjectServiceImpl3上的@Component注解,避免Spring自动生成默认实例,然后通过配置类创建两个指定依赖的实例:

@Configuration
public class AffectedObjectConfig {

    // 创建依赖XYZInterfaceImpl1的实例
    @Bean
    public AffectedObjectService serviceImpl3WithXyz1(XYZInterfaceImpl1 xyzImpl1) {
        return new AffectedObjectServiceImpl3(xyzImpl1);
    }

    // 创建依赖XYZInterfaceImpl2的实例
    @Bean
    public AffectedObjectService serviceImpl3WithXyz2(XYZInterfaceImpl2 xyzImpl2) {
        return new AffectedObjectServiceImpl3(xyzImpl2);
    }
}

Spring会自动将这两个Bean加入到List<AffectedObjectService>中,工厂类的构造器就能获取到这两个实例。

方式二:结合@Qualifier限定依赖

如果需要更灵活的依赖选择,可以给XYZInterface的实现类添加@Qualifier标记,再在配置类中指定依赖:

  1. 给XYZInterface实现类添加限定符:
@Component
@Qualifier("xyzImpl1")
class XYZInterfaceImpl1 implements XYZInterface {
    @Override
    String func2() { // .... }
}

@Component
@Qualifier("xyzImpl2")
class XYZInterfaceImpl2 implements XYZInterface {
    @Override
    String func2() { // .... }
}
  1. 在配置类中创建实例时指定依赖:
@Configuration
public class AffectedObjectConfig {

    @Bean
    public AffectedObjectService serviceImpl3WithXyz1(@Qualifier("xyzImpl1") XYZInterface xyzInterface) {
        return new AffectedObjectServiceImpl3(xyzInterface);
    }

    @Bean
    public AffectedObjectService serviceImpl3WithXyz2(@Qualifier("xyzImpl2") XYZInterface xyzInterface) {
        return new AffectedObjectServiceImpl3(xyzInterface);
    }
}

关键注意事项

  1. 必须移除AffectedObjectServiceImpl3的@Component注解,否则Spring会尝试自动创建一个实例,若存在多个XYZInterface实现会直接导致依赖注入失败。
  2. 修正原代码中的两处语法错误:
    • AffectedObjectService接口的func1方法返回值需与工厂类调用逻辑保持一致,改为String[];
    • XYZInterface是接口,其实现类需用implements关键字而非extends。

内容的提问来源于stack exchange,提问作者Noor Ahmad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 17:01:36