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

Spring中RestController如何调用其他组件处理对象并保存至另一仓库?

问题分析

你遇到的核心问题是:手动new出来的SimulationProcess对象并不受Spring容器管理,所以里面通过@Autowired注入的SecondRepository会是null,根本没法执行保存操作。Spring的依赖注入只对它自己创建并管理的Bean生效,手动实例化的对象不在这个范围内。

下面给你两种可行的解决方案,分别对应不同的场景:


方案1:把SimulationProcess改成无状态的Spring Service(推荐)

这种方式是Spring里最常用的做法,把SimulationProcess设计成无状态的单例Bean,通过方法参数传递Simulation对象,而不是把它存在实例变量里。这样既符合Spring的设计理念,又保证线程安全。

首先修改SimulationProcess:

// 用@Service标记让Spring把它管理成单例Bean
@Service
public class SimulationProcess {
    // 用构造器注入依赖,Spring 4.3+可以不用写@Autowired
    private final SecondRepository secondRepository;

    public SimulationProcess(SecondRepository secondRepository) {
        this.secondRepository = secondRepository;
    }

    // 把Simulation作为方法参数传入,而不是存在实例变量中
    public void simulate(Simulation simulation) {
        // 处理simulation中的数据,比如提取字段创建Second对象
        Second secondEntity = new Second();
        // 假设Second有个simulationId字段,对应Simulation的id
        secondEntity.setSimulationId(simulation.getId());
        // 其他字段处理...
        
        secondRepository.save(secondEntity);
    }
}

然后在你的SimulationController里注入这个Service:

@RestController
@RequestMapping("/api")
public class SimulationController {
    private final SimulationRepository simulationRepository;
    private final SimulationProcess simulationProcess;

    // 构造器注入两个Repository和Service,避免字段注入的弊端
    public SimulationController(SimulationRepository simulationRepository, SimulationProcess simulationProcess) {
        this.simulationRepository = simulationRepository;
        this.simulationProcess = simulationProcess;
    }

    @PostMapping("/simulations")
    public Simulation createSimulation(@Valid @RequestBody Simulation simulation) {
        Simulation savedSimulation = simulationRepository.save(simulation);
        // 直接调用service的方法,传入保存后的simulation(此时已经有id了)
        simulationProcess.simulate(savedSimulation);
        return savedSimulation;
    }
}

方案2:如果需要有状态的SimulationProcess(原型Bean)

如果你确实需要每个请求对应一个独立的SimulationProcess实例(比如要在实例中保存一些请求相关的状态),可以把它标记为原型作用域(prototype),然后通过Spring的工厂来获取实例,这样Spring会帮你注入依赖。

首先修改SimulationProcess:

@Component
// 标记为原型作用域,每次获取都会创建新实例
@Scope("prototype")
public class SimulationProcess {
    private final Simulation simulation;
    private final SecondRepository secondRepository;

    // 构造器同时注入依赖和Simulation对象
    public SimulationProcess(Simulation simulation, SecondRepository secondRepository) {
        this.simulation = simulation;
        this.secondRepository = secondRepository;
    }

    public void simulate() {
        // 直接使用实例中的simulation处理数据
        Second secondEntity = new Second();
        secondEntity.setSimulationId(simulation.getId());
        // 其他处理...
        
        secondRepository.save(secondEntity);
    }
}

然后在Controller里用ObjectFactory来获取原型实例:

@RestController
@RequestMapping("/api")
public class SimulationController {
    private final SimulationRepository simulationRepository;
    private final ObjectFactory<SimulationProcess> simulationProcessFactory;

    public SimulationController(SimulationRepository simulationRepository, ObjectFactory<SimulationProcess> simulationProcessFactory) {
        this.simulationRepository = simulationRepository;
        this.simulationProcessFactory = simulationProcessFactory;
    }

    @PostMapping("/simulations")
    public Simulation createSimulation(@Valid @RequestBody Simulation simulation) {
        Simulation savedSimulation = simulationRepository.save(simulation);
        // 通过ObjectFactory获取原型实例,并传入savedSimulation
        SimulationProcess simulationProcess = simulationProcessFactory.getObject(savedSimulation);
        simulationProcess.simulate();
        return savedSimulation;
    }
}

为什么原来的方式不行?

再强调一下:当你手动new SimulationProcess(simulation)时,这个对象完全脱离了Spring的控制。Spring不会自动注入它里面的SecondRepository,所以调用simulate()方法时会抛出NullPointerException。只有Spring自己创建的Bean(比如通过@Service、@Component标记,或者XML配置的),才会触发依赖注入流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:03:49