本质原因:spring管理的都是单例(singleton),和 websocket (多对象)相冲突。
详细解释:项目启动时初始化,会初始化 websocket (非用户连接的),spring 同时会为其注入 service,该对象的 service 不是 null,被成功注入。但是,由于 spring 默认管理的是单例,所以只会注入一次 service。当新用户进入聊天时,系统又会创建一个新的 websocket 对象,这时矛盾出现了:spring 管理的都是单例,不会给第二个 websocket 对象注入 service,所以导致只要是用户连接创建的 websocket 对象,都不能再注入
解决办法:
1通过spring上下文获取获取bean(已验证,可用)
@Component public class SpringContextUtil implements ApplicationContextAware { /** * 打印日志 */ private Logger logger = LoggerFactory.getLogger(getClass()); /** * 获取上下文对象 */ private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextUtil.applicationContext = applicationContext; logger.info("set applicationContext"); } /** * 获取 applicationContext * * @return */ public static ApplicationContext getApplicationContext() { return applicationContext; } /** * 通过 name 获取 bean 对象 * * @param name * @return */ public static Object getBean(String name) { return getApplicationContext().getBean(name); } /** * 通过 class 获取 bean 对象 * * @param clazz * @param <T> * @return */ public static <T> T getBean(Class<T> clazz) { return getApplicationContext().getBean(clazz); } /** * 通过 name,clazz 获取指定的 bean 对象 * * @param name * @param clazz * @param <T> * @return */ public static <T> T getBean(String name, Class<T> clazz) { return getApplicationContext().getBean(name, clazz); } }
通过name,class来获取相应的bean即可
private TestService testService = SpringContextUtil.getBean(TestService.class);
2.将要注入的 service 改成 static(未验证)
@ServerEndpoint(value="/MySocket") public class MySocket{ // 这里使用静态,让 service 属于类 private static TestService testService;
// 注入的时候,给类的 service 注入
@Autowired
public void setTestService(TestService testService) {
MySocket.testService= testService;
} }