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

SpringBoot如何自动装配含非托管类构造参数的类?

解决SpringBoot中自动装配带外部构造参数的原型Bean问题

首先,先明确你的核心需求:创建一个每次调用都生成新实例的Prototype类,它既要依赖Spring托管的组件(比如Repository),又需要接收外部传入的非Spring托管对象(比如WebSocket的Session)。下面一步步给你解决:

1. 修正Prototype的作用域与依赖注入方式

首先,你的Prototype类必须标记为原型作用域,否则Spring默认会创建单例,即使调用getBean也只会返回同一个实例。另外,推荐用构造注入托管的依赖(比如Repository),外部参数用Setter注入,这样既符合Spring的依赖注入规范,又能灵活传入外部对象:

@Component
@Scope("prototype") // 明确标记为原型作用域,确保每次获取都是新实例
class Prototype {
    private final Repository repository;
    private Session session;

    // 构造注入Spring托管的Repository,Spring会自动完成这部分注入
    public Prototype(Repository repository) {
        this.repository = repository;
    }

    // Setter方法用于手动传入外部的Session对象
    public void setSession(Session session) {
        this.session = session;
    }
}

2. 正确获取原型实例并传入外部参数

在PrototypeClient中,你通过ApplicationContext.getBean(Prototype.class)获取新的原型实例,然后调用Setter传入Session即可。这种方式是正确的,只要Prototype是原型作用域,每次调用都会生成新实例:

@Component
class PrototypeClient {
    @Autowired
    private ApplicationContext context;

    public void createNewPrototype(Session session) {
        // 获取新的Prototype实例(原型作用域保证每次都是新的)
        Prototype prototype = context.getBean(Prototype.class);
        // 手动设置外部传入的Session
        prototype.setSession(session);
        // 现在prototype同时拥有Spring注入的Repository和外部的Session了
    }
}

3. 修正WebSocketController的Bean获取方式

你原来的WebSocketController中直接用静态方法获取PrototypeClient是不规范的,而且@ServerEndpoint注解的类默认不会被Spring托管,需要做两步调整:

  • 给WebSocketController加上@Component,让Spring管理它
  • 配置ServerEndpointExporter,让Spring识别WebSocket端点
  • 用@Autowired注入PrototypeClient,而不是静态获取

调整后的代码:

@Component
@ServerEndpoint(value = "/resources")
class WebSocketController {
    @Autowired
    private PrototypeClient client;

    @OnMessage
    void handleMessage(Session session, String message) {
        client.createNewPrototype(session);
    }
}

// 新增WebSocket配置类
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

关于你之前的报错原因

你之前调用context.getBean(Prototype.class, session)报错,是因为你的Prototype构造函数只有Session参数,Spring会尝试在容器中查找Session类型的Bean,但Session是外部传入的非Spring托管对象,所以找不到而报错。用构造注入托管依赖+Setter注入外部参数的方式,就可以避免这个问题。

补充:获取原型实例的方式是否正确?

你的思路是对的——因为需要每次生成新实例,不能用@Autowired直接注入(默认会注入单例),通过ApplicationContext.getBean获取原型作用域的Bean是正确的做法,只要确保Prototype标记了@Scope("prototype")即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:11:32