spring springboot websocket 不能注入( @Autowired ) service bean 报 null 错误

在Spring或SpringBoot的WebSocket中使用@Autowired注入Service时,可能会遇到Service为null的问题。原因是Spring管理的单例bean与WebSocket的多对象特性冲突。解决办法是将Service字段声明为static。详细解释涉及WebSocket的多对象机制与Spring初始化过程,确保每个WebSocket对象的Service非null,从而保证安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spring 或 springboot 的 websocket 里面使用 @Autowired 注入 service 或 bean 时,报空指针异常,service 为 null(并不是不能被注入)。

解决方法:将要注入的 service 改成 static,就不会为null了。

参考代码:

@Controller
@ServerEndpoint(value="/chatSocket")
public class ChatSocket {
    //  这里使用静态,让 service 属于类
    private static ChatService chatService;

    // 注入的时候,给类的 service 注入
    @Autowired
    public void setChatService(ChatService chatService) {
        ChatSocket.chatService = chatService;
    }
}
本质原因:spring管理的都是单例(singleton)和 websocket (多对象)相冲突。

需要了解一个事实:websocket 是多对象的,每个用户的聊天客户端对应 java 后台的一个 websocket 对象,前后台一对一(多对多)实时连接,所以 websocket 不可能像 servlet 一样做成单例的,让所有聊天用户连接到一个 websocket对象,这样无法保存所有用户的实时连接信息。可能 spring 开发者考虑

### 集成WebSocket并正确注入Bean #### 导入WebSocket依赖 为了在Spring Boot项目中集成WebSocket,首先需要引入必要的依赖项。这可以通过修改`pom.xml`文件来完成,在其中加入WebSocket的支持库[^2]。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` #### 创建WebSocket配置类 接着定义一个用于配置WebSocket行为的Java类。此类通常会继承自`AbstractSessionWebSocketMessageBrokerConfigurer`或者实现`WebSocketMessageBrokerConfigurer`接口,并重写相应的方法以定制化WebSocket的功能设置。 #### 实现消息处理端点 创建带有`@ServerEndpoint`注解的服务端点类,该类负责监听特定路径上的连接请求以及接收来自客户端的消息。需要注意的是,在这个类里面可以直接通过构造函数参数列表的方式自动装配所需的Spring管理对象;然而有时可能会遇到无法成功注入的情况,这时可以考虑采用静态上下文工具类动态获取所需bean实例作为替代方案[^3]。 对于因某些原因导致的标准DI机制失效的情形下,可以在检测到成员变量为空时手动从应用上下文中取出对应的bean: ```java if(this.webSocketStore == null){ this.webSocketStore = (WebSocketStore) SpringContextUtil.getBean("webSocketStore"); } ``` 这种方法虽然不是最优雅的选择,但在特殊场景下确实能够解决问题[^4]。 #### 完整示例代码片段 下面给出一段完整的代码样例,展示了如何在一个基于Spring Boot的应用程序里启用WebSocket支持并且安全可靠地执行Bean注入操作。 ```java // WebSocketConfig.java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").withSockJS(); } } // MyWebSocketHandler.java @Component @ServerEndpoint(value="/chat/{userId}") public class MyWebSocketHandler { private final Logger logger = LoggerFactory.getLogger(MyWebSocketHandler.class); // 使用@Autowired进行标准的依赖注入尝试 @Autowired private SomeService someService; // 如果上述方式不奏效,则可在此处提供备用加载逻辑 private transient volatile SomeService fallbackSomeService; @OnOpen public void onOpen(Session session, @PathParam("userId") String userId) throws IOException{ if(someService==null && fallbackSomeService!=null){ synchronized(this){ if(fallbackSomeService==null){ ApplicationContext context=ApplicationContextProvider.getApplicationContext(); fallbackSomeService=context.getBean(SomeService.class); } } } // ...其余业务逻辑... } } ```
评论 94
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值