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

Spring中Map<String, DataTablesRepository>键不符合预期问题求助

问题:Spring Service中手动初始化的Repository映射Map键不符合预期

问题描述

尝试在Spring的@Service类中定义一个Map<String, DataTablesRepository>来映射多个JPA Repository,代码如下:

@Service
@AllArgsConstructor
public class MyDataTablesService {

    private final RegistroDtRepository registroDtRepository;
    private final ContinentiDtRepository continentiDtRepository;

    public Map<String, DataTablesRepository> repositories = this.createMap();

    public DataTablesOutput<?> findAllDatatable(String repoId, DataTablesInput input) {

        System.out.println(this.repositories);

        DataTablesRepository repository = this.repositories.get(repoId);

        DataTablesOutput<?> res = repository.findAll(input);
        return res;
    }

    private Map<String, DataTablesRepository> createMap(){
        Map<String, DataTablesRepository> myMap = new HashMap<String, DataTablesRepository>();
        myMap.put("continenti", this.continentiDtRepository);
        myMap.put("registro", this.registroDtRepository);
        return myMap;
    }
}

调用findAllDatatable方法时,预期控制台输出的Map键为自定义的"registro"和"continenti":

{registro=org.springframework.data.jpa.datatables.repository.DataTablesRepositoryImpl@2aec0c10, continenti=org.springframework.data.jpa.datatables.repository.DataTablesRepositoryImpl@1bf71fb7}

但实际输出的键却是成员变量名:

{registroDtRepository=org.springframework.data.jpa.datatables.repository.DataTablesRepositoryImpl@2aec0c10, continentiDtRepository=org.springframework.data.jpa.datatables.repository.DataTablesRepositoryImpl@1bf71fb7}

导致通过this.repositories.get("continenti")获取Repository时返回null。

问题原因

Spring有自动注入集合类型依赖的特性:当容器中存在Map<String, T>类型的成员变量时,Spring会自动收集所有类型为T的Bean,并以Bean的名称(这里就是你声明的成员变量名registroDtRepository、continentiDtRepository)作为键,填充到这个Map中。

你在成员变量声明时手动初始化的repositories被Spring的自动注入行为覆盖了,最终使用的是Spring自动生成的Map,而非你自定义的Map。

解决方法

方法1:使用@PostConstruct初始化Map

利用Spring的生命周期注解@PostConstruct,确保在所有依赖注入完成后再初始化自定义Map:

@Service
@AllArgsConstructor
public class MyDataTablesService {

    private final RegistroDtRepository registroDtRepository;
    private final ContinentiDtRepository continentiDtRepository;

    private Map<String, DataTablesRepository> repositories;

    @PostConstruct
    private void initRepositoryMap() {
        repositories = new HashMap<>();
        repositories.put("continenti", continentiDtRepository);
        repositories.put("registro", registroDtRepository);
    }

    public DataTablesOutput<?> findAllDatatable(String repoId, DataTablesInput input) {
        System.out.println(this.repositories);
        DataTablesRepository repository = this.repositories.get(repoId);
        return repository.findAll(input);
    }
}

方法2:在构造函数中初始化Map

通过构造函数直接初始化Map,避免Spring自动注入的干扰:

@Service
public class MyDataTablesService {

    private final RegistroDtRepository registroDtRepository;
    private final ContinentiDtRepository continentiDtRepository;
    private final Map<String, DataTablesRepository> repositories;

    // 手动编写构造函数,替换Lombok的@AllArgsConstructor
    public MyDataTablesService(RegistroDtRepository registroDtRepository, ContinentiDtRepository continentiDtRepository) {
        this.registroDtRepository = registroDtRepository;
        this.continentiDtRepository = continentiDtRepository;
        this.repositories = new HashMap<>();
        this.repositories.put("continenti", continentiDtRepository);
        this.repositories.put("registro", registroDtRepository);
    }

    public DataTablesOutput<?> findAllDatatable(String repoId, DataTablesInput input) {
        System.out.println(this.repositories);
        DataTablesRepository repository = this.repositories.get(repoId);
        return repository.findAll(input);
    }
}

关键说明

  • 将repositories改为private可以降低Spring自动注入的优先级,避免被自动填充;
  • @PostConstruct是Spring官方推荐的初始化方式,确保依赖完全注入后再执行自定义逻辑,是最稳妥的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 17:57:15