WebSocket类明明注入了Bean,为什么报错为null

在 WebSocket 类中注入 Bean 看似可行而注入 Bean 报错为null,通常是由于Spring 的单例管理机制与 WebSocket 多实例创建特性冲突导致的,具体分析如下:

原因分析

  • Spring 的单例特性 :Spring 默认以单例模式管理 Bean,即一个 Bean 在容器中只创建一次。项目启动时,会初始化一个 WebSocket 实例(非用户连接时),此时 Spring 会为该实例注入 Bean,该实例的 Bean 不会为null
  • WebSocket 的多实例创建 :当新用户连接时,系统会创建新的 WebSocket 实例。由于 Spring 的单例机制,不会为后续创建的 WebSocket 实例再注入 Bean,导致这些新实例中的 Bean 为null

解决方案

通过ApplicationContext手动获取 Bean,绕过 Spring 自动注入的单例限制,确保每个 WebSocket 实例能获取到 Bean。步骤如下:

  1. 创建 Spring 上下文工具类

    复制代码
    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    
    @Component
    public class SpringContextUtil implements ApplicationContextAware {
        private static ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            SpringContextUtil.applicationContext = applicationContext;
        }
    
        public static ApplicationContext getApplicationContext() {
            return applicationContext;
        }
    
        public static <T> T getBean(Class<T> clazz) {
            return applicationContext.getBean(clazz);
        }
    }
  2. 在 WebSocket 类中手动获取 Bean

    复制代码
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    import org.springframework.stereotype.Component;
    
    @Component
    @ServerEndpoint("/hot-search-ws")
    public class WebSocketServerSearch {
        private HotSearchService hotSearchService;
    
        @javax.websocket.OnOpen
        public void onOpen(Session session) {
            // 手动获取service
            hotSearchService = SpringContextUtil.getBean(HotSearchService.class);
            sendHotSearches(session);
        }
    
        private void sendHotSearches(Session session) {
            try {
                if (hotSearchService != null) {
                    List<HotSearch> randomHotSearches = hotSearchService.getRandomHotSearches(5);
                    String hotSearchList = randomHotSearches.stream()
                            .map(HotSearch::getText)
                            .collect(Collectors.joining("\n"));
                    session.getBasicRemote().sendText(hotSearchList);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    通过上述方法,每个 WebSocket 实例在需要时主动从 Spring 上下文中获取 Bean,避免因单例注入机制导致的null问题。

相关推荐
豆奶特浓69 分钟前
谢飞机勇闯Java面试:从内容社区的缓存一致性到AI Agent,这次能飞多高?
java·微服务·ai·面试·架构·缓存一致性·feed流
Pou光明10 分钟前
7_线程安全_线程间的内存可视性2缓存_内存屏障_读写排序
java·开发语言·缓存
CV_J14 分钟前
L12_用户菜单权限
java
来旺15 分钟前
互联网大厂Java面试实战:核心技术栈与业务场景深度解析
java·spring boot·docker·kubernetes·mybatis·hibernate·microservices
big-seal16 分钟前
XML解释
xml·java·数据库
m***119024 分钟前
Spring BOOT 启动参数
java·spring boot·后端
小石头 1008626 分钟前
【JavaEE】synchronized关键字
java·java-ee
悟空码字27 分钟前
Java实现接口幂等性:程序员的“后悔药”
java·后端
天天摸鱼的java工程师28 分钟前
🔍 MySQL 索引底层原理与 SQL 优化实战:从 B + 树到亿级查询优化
java·后端
IMPYLH31 分钟前
Lua 的 select 函数
java·开发语言·笔记·后端·junit·游戏引擎·lua