龙空技术网

Springboot+Websocket中@Autowired注入service为null的解决方法

黄三技术说 167

前言:

当前朋友们对“netcore service为null”大概比较重视,姐妹们都想要剖析一些“netcore service为null”的相关内容。那么小编也在网络上搜集了一些关于“netcore service为null””的相关文章,希望小伙伴们能喜欢,小伙伴们快快来学习一下吧!

在Websocket中使用@Autowired注入service时注入失败,service为null。

问题原因

Spring默认对bean的管理都是单例(singleton),和 websocket (多对象)相冲突。

项目启动时初始化,会初始化 websocket (非用户连接的),spring 同时会为其注入 service,该对象的 service 不是 null,被成功注入。但是,由于 spring 默认管理的是单例,所以只会注入一次 service。当用户建立新的连接时,系统又会创建一个新的 websocket 对象,这时不会再次注入了,所以导致只要是用户连接创建的 websocket 对象,都不能再注入了,后面的注入均为null。

解决方法

方法1:使用静态变量 加 @PostConstruct 解决

@ServerEndpoint("/websocket/{userId}") @Component //关键点1 public class WebSocket {        @Autowired        private UserService userService;        private static WebSocket webSocket;       //关键点2    @PostConstruct //关键点3     public void init(){       	webSocket = this;      }     //略去其他代码...      @OnMessage      public void onMessage(String message, Session session) {          if(!StringUtils.isEmpty(message)){            try {              log.info("收到用户【{}】的消息: {}",this.userId,message);              webSocket.userService.helloService(); //关键点4              session.getBasicRemote().sendText("收到 "+this.userId+" 的消息 ");            }catch (Exception e){              e.printStackTrace();          }      }    }}

配置完上述四个关键点,当新建立websocket连接时,@Autowired可成功注入service

方法2:使用静态变量,加set注入

@ServerEndpoint("/websocket/{userId}")@Component //关键点1 public class WebSocket {      private static UserService userService; //关键点2      @Autowired //关键点3       public void setUserService (UserService userService){         WebSocket.userService = userService;      }    //略去其他代码...       @OnMessage public void onMessage(String message, Session session) {           if(!StringUtils.isEmpty(message)){               try {                   log.info("收到用户【{}】的消息: {}",this.userId,message);                   WebSocket.userService.helloService(); //关键点4                    session.getBasicRemote().sendText("收到 "+this.userId+" 的消息 ");               }catch (Exception e){                 e.printStackTrace();               }          }      } }

配置完上述四个关键点,当新建立websocket连接时,@Autowired也可成功注入service

方法3:使用工具类用于从Spring的上下文中去获取到类的实例

@ServerEndpoint("/websocket/{userId}") @Component //关键点1 public class WebSocket {     private static UserService userService = SpringContextHolder.getBean(UserService.class); //关键点2   //略去其他代码...    @OnMessage    public void onMessage(String message, Session session) {        if(!StringUtils.isEmpty(message)){               try {                 log.info("收到用户【{}】的消息: {}",this.userId,message);                 userService.helloService(); //关键点3                 session.getBasicRemote().sendText("收到 "+this.userId+" 的消息 ");              }catch (Exception e){                 e.printStackTrace();               }         }    }}

工具类SpringContextHolder

此工具类用于从Spring的上下文中去获取到类的实例

@Component public class SpringContextHolder implements ApplicationContextAware {   	private static ApplicationContext applicationContext = null;     /** * 取得存储在静态变量中的ApplicationContext. */     public static ApplicationContext getApplicationContext() {         return applicationContext;     }     /* * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */    @SuppressWarnings("unchecked")     public static <T> T getBean(String name) {            return (T) applicationContext.getBean(name);    }     /* * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */     public static <T> T getBean(Class<T> requiredType) {       return applicationContext.getBean(requiredType);    }     /* * 清除SpringContextHolder中的ApplicationContext为Null. */     public static void clearHolder() {       applicationContext = null;     }     /* * 实现ApplicationContextAware接口, 注入Context到静态变量中. */    @Override    public void setApplicationContext(ApplicationContext appContext) {       applicationContext = appContext;    } }

配置完上述三个关键点,当新建立websocket连接时,@Autowired也可成功注入service

标签: #netcore service为null