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

Spring Boot中注入Bean与手动创建Bean的混合使用方案问询

Spring Boot中混合注入服务与运行时参数创建实例的方案

问题场景

我有两个类,一个服务类如下:

@Service
public class CharacterService {
    @Autowired
    private SimpMessagingTemplate websocket;

    @Autowired
    ArtifactsClient artifactsClient;
    public void bringWoodToBank(String characterName) {
        ....            
        new DepositTask(character, deposit, artifactsClient, websocket, this);
        }
    }

另一个任务类:

public class DepositTask implements Task {

    Logger log = LoggerFactory.getLogger(DepositTask.class);

    private final ArtifactsClient artifactsClient;

    private final SimpMessagingTemplate websocket;

    private final CharacterService characterService;

    private de.sveri.artifactsmmo.entities.Character character;

    private Deposit deposit;

    public DepositTask(de.sveri.artifactsmmo.entities.Character character, Deposit deposit,
            ArtifactsClient artifactsClient, SimpMessagingTemplate websocket, CharacterService characterService) {
        this.character = character;
        this.deposit = deposit;
        this.artifactsClient = artifactsClient;
        this.websocket = websocket;
        this.characterService = characterService;
    }
}

由于DepositTask需要传入仅运行时可用的character和deposit参数,无法直接标记为@Service。现在想知道Spring/Spring Boot有没有相关模式,可以让DepositTask自动注入所需服务,或者实现注入参数与非注入参数的混合传递?

解决方案

方案1:工厂模式(推荐)

创建一个Spring管理的工厂类,将需要注入的服务统一托管在工厂中,再通过工厂方法接收运行时参数来创建DepositTask实例:

@Service
public class DepositTaskFactory {
    private final ArtifactsClient artifactsClient;
    private final SimpMessagingTemplate websocket;
    private final CharacterService characterService;

    // 构造注入Spring托管的服务
    public DepositTaskFactory(ArtifactsClient artifactsClient, SimpMessagingTemplate websocket, CharacterService characterService) {
        this.artifactsClient = artifactsClient;
        this.websocket = websocket;
        this.characterService = characterService;
    }

    // 提供创建任务的方法,仅接收运行时动态参数
    public DepositTask createTask(de.sveri.artifactsmmo.entities.Character character, Deposit deposit) {
        return new DepositTask(character, deposit, artifactsClient, websocket, characterService);
    }
}

修改CharacterService,注入工厂后直接调用创建方法:

@Service
public class CharacterService {
    @Autowired
    private DepositTaskFactory depositTaskFactory;

    public void bringWoodToBank(String characterName) {
        ....            
        DepositTask task = depositTaskFactory.createTask(character, deposit);
        }
    }

方案2:@Configurable结合AspectJ(不推荐)

给DepositTask添加@Configurable注解,让Spring为通过new创建的实例自动注入依赖,但需要启用AspectJ编译时织入,配置复杂度高且侵入性强:

@Configurable
public class DepositTask implements Task {
    @Autowired
    private ArtifactsClient artifactsClient;
    @Autowired
    private SimpMessagingTemplate websocket;
    @Autowired
    private CharacterService characterService;

    private de.sveri.artifactsmmo.entities.Character character;
    private Deposit deposit;

    // 仅接收运行时参数的构造方法
    public DepositTask(de.sveri.artifactsmmo.entities.Character character, Deposit deposit) {
        this.character = character;
        this.deposit = deposit;
    }
}

同时需要在启动类添加@EnableSpringConfigured,并在构建工具中配置AspectJ相关依赖与插件,这种方式排查问题难度大,一般不建议使用。

方案3:ObjectProvider(适合复杂场景)

在CharacterService中注入ObjectProvider<DepositTask>,通过其getObject方法传入运行时参数:

@Service
public class CharacterService {
    @Autowired
    private ObjectProvider<DepositTask> depositTaskProvider;

    public void bringWoodToBank(String characterName) {
        ....            
        DepositTask task = depositTaskProvider.getObject(character, deposit);
        }
    }

DepositTask需使用@Autowired标记构造方法,区分注入服务与运行时参数:

public class DepositTask implements Task {
    private final ArtifactsClient artifactsClient;
    private final SimpMessagingTemplate websocket;
    private final CharacterService characterService;
    private final de.sveri.artifactsmmo.entities.Character character;
    private final Deposit deposit;

    @Autowired
    public DepositTask(ArtifactsClient artifactsClient, SimpMessagingTemplate websocket, CharacterService characterService,
            de.sveri.artifactsmmo.entities.Character character, Deposit deposit) {
        this.artifactsClient = artifactsClient;
        this.websocket = websocket;
        this.characterService = characterService;
        this.character = character;
        this.deposit = deposit;
    }
}

该方式需Spring 4.3+支持,且要确保构造参数顺序匹配,可读性不如工厂模式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 18:50:10