在 WebSocket 中使用 @Autowired 时遇到空指针异常
背景:在websocket在有新的连接加入进来时,调用servier中的服务,使用 @Autowired
注入的 Bean 竟然是 null
!这并非 Spring 的 Bug,而是对 WebSocket 生命周期管理理解不足导致的。
了解这个问题,我们需要区分两个关键概念:
- Spring 容器: 负责管理 Bean 的生命周期,包括实例化、依赖注入和销毁。
- WebSocket 容器: 负责管理 WebSocket 端点的生命周期,例如建立连接、接收消息和关闭连接。
默认情况下,WebSocket 容器负责创建 @ServerEndpoint
注解的类的实例,并且不会使用 Spring 的依赖注入机制。 这意味着即使你使用了 @Component
注解,Spring 容器也不会自动将 Bean 注入到 WebSocket 端点类中。
一些文章将此问题归咎于 Spring Bean 的单例特性与 WebSocket 端点类的多例特性之间的冲突。这种说法并不准确。 Spring 的依赖注入机制并不限制单例 Bean 注入到多例 Bean 中。
问题的根源在于:Spring 容器根本没有参与 WebSocket 端点类的实例化过程,因此依赖注入也就无从谈起。
可以使用上下文类来得到:
@Component public class SpringContextHolder implements ApplicationContextAware {private static ApplicationContext context;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {SpringContextHolder.context = applicationContext;}public static <T> T getBean(Class<T> clazz) {return context.getBean(clazz);} }
在使用的时候,get需要的
SpringContextHolder.getBean(MetalDefectDetectionService.class);