关于使用WebSocket时无法使用@Autowired 注入的问题

发布于:2025-06-12 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

根本原因:WebSocket 类不是由 Spring 管理的 Bean 实例

解决方案:手动从 Spring 容器中获取 Bean

1. 创建 Spring 上下文工具类:

 2. 在 WebSocket 中使用:


虽然加上了 @Component,但 在 WebSocket 的生命周期回调方法中使用 @Autowired 注入其他 Bean 时会失败,这是因为:

根本原因:WebSocket 类不是由 Spring 管理的 Bean 实例

尽管你加了 @Component,Spring 确实会把这个类作为一个 Bean 注册到容器中。但是,Java 的 WebSocket API(JSR-356)在创建 @ServerEndpoint 对应的类实例时,并不是通过 Spring 容器来创建的,而是由底层的 WebSocket 容器(如 Tomcat、Jetty)直接 new 出来的。

也就是说:

  • Spring 创建了一个 WebSocketServer 实例(作为 Bean)
  • WebSocket 容器又自己 new 了一个 WebSocketServer 实例(用于处理连接)
  • 这个 new 出来的实例并没有被 Spring 管理,所以里面的 @Autowired 字段是 null
@Component
@ServerEndpoint("/webSocket/{userId}")
public class WebSocketServer {

    @Autowired
    private SomeService someService; // 会是 null

    @OnOpen
    public void onOpen(...) {
        someService.doSomething(); // NullPointerException!
    }
}

解决方案:手动从 Spring 容器中获取 Bean

你可以通过一个工具类,从 Spring 容器中手动获取你需要的 Bean。

1. 创建 Spring 上下文工具类:

​
@Component
public class SpringContextUtils implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        context = applicationContext;
    }

    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }

    public static <T> T getBean(String name, Class<T> beanClass) {
        return context.getBean(name, beanClass);
    }
}

​

 2. 在 WebSocket 中使用:

@Component
@ServerEndpoint("/webSocket/{userId}")
public class WebSocketServer {

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        SomeService someService = SpringContextUtils.getBean(SomeService.class);
        someService.doSomething();
    }
}