spring 或 springboot 的 websocket 里面使用 @Autowired 注入 service 或 bean 时,报java.lang.NullPointerException异常,service为null(实际上并非不能被注入)java
将要注入的 service 改为 static,而后添加一个set方法(重要的事情说三遍:这个set方法必定不能是static的,这个set方法必定不能是static的,这个set方法必定不能是static的)就不会为null了。通过测试,接口和实现类都是能够成功注入的。web
参考代码:spring
@Controller @ServerEndpoint("chatSocket") public class ImSer { // 这里使用静态,让 service 属于类 private static ChatService chatService; // 注入的时候,给类的 service 注入,注意:这个set方法必定不能是静态的 @Autowired public void setChatService(ChatService chatService) { ImSer.chatService = chatService; } }
本质缘由:spring管理的都是单例(singleton)和 websocket (多对象)相冲突
websocket 是多对象的,每一个用户的聊天客户端对应 java 后台的一个 websocket 对象,先后台一对一(多对多)实时链接,因此 websocket 不可能像 servlet 同样作成单例的,让全部聊天用户链接到一个 websocket对象,这样没法保存全部用户的实时链接信息。可能 spring 开发者考虑到这个问题,没有让 spring 建立管理 websocket ,而是由 java 原来的机制管理websocket ,因此用户聊天时建立的 websocket 链接对象不是 spring 建立的,spring 也不会为不是他建立的对象进行依赖注入,因此若是不用static关键字,每一个 websocket 对象的 service 都是 null
详细解释(按上面我写的代码,假设属性使用了 static):
初始化:项目启动时,spring 工厂会建立 websocket 的单例对象(此时注解合法,spring 就会为 ChatSocket 类的属性 ChatService 进行注入,并建立一个单例对象,spring 并不知道 websocket 的特殊意义,只是该类的注解合法,便会进行操做,与其余 controller 进行的操做如出一辙),所以 chatService 不是 null。
聊天时:当新用户经过客户端聊天时,后台(无论是tomcat 仍是java)会根据 ChatSocket 类建立一个新的 chatSocket 对象,保存与用户的链接。由于chatService 是属于类的,因此也不是 null。
总结:
这里 websocket 的多对象机制和 spring 的 controller 注解机制,同时进行,互相没有矛盾。spring 会在初始化时建立一个没有意义的 ChatSocket 的单例对象,该对象在运行期间一直不会被使用,同时为 ChatSocket 的类进行了静态属性的完善,这是 spring 的惟一做用。
当有用户链接聊天时,java 会根据 ChatSocket 类进行建立对象,每一个对象保持与对应的用户链接,由于类的静态属性已在启动时被 spring 初始化了,因此每一个对象均可以正常使用。
安全性:
安全性要高于单例模式。单例模式全程使用一个对象,而 websocket 使用了多个对象,每一个对象互相独立,属性互相分开,惟一的静态属性chatService,只是调用了其方法而已。若是心里实在惧怕,本身根据实际状况在 chatService 中使用同步,或者加锁。tomcat
转载自:https://blog.csdn.net/m0_37202351/article/details/86255132,感谢原做者的无私奉献安全