在非标准Spring组件中(比如websocket)注入Spring管理bean的方法
private static UserMapper userMapper;
@Autowired
public void setUserMapper(UserMapper userMapper) {
WebSocketServer.userMapper = userMapper;
}
WebSocketServer
是通过Java WebSocket API创建的,并且由于@ServerEndpoint
不是Spring的标准组件注解,直接在其中使用@Autowired
进行依赖注入通常是行不通的。这就需要采用一种特殊的方式来实现依赖注入。
private static UserMapper userMapper;
:这是对UserMapper
的静态声明。UserMapper是一个接口,通过MyBatis或MyBatis Plus等ORM框架与数据库进行交互的Mapper。由于WebSocketServer
实例可能会有多个,而UserMapper
应该是一个全局单例(与数据库的交互通常是线程安全的,且不需要每个WebSocket连接都创建一个新的实例),因此这里使用static
修饰符。
(ORM框架:允许开发者在编程时使用面向对象的方式来操作数据库中的数据,而不是通过直接编写SQL语句。ORM框架会负责将面向对象的操作转换为适当的数据库操作。)
@Autowired
:这是Spring的注解,用于自动注入依赖。但是由于WebSocketServer类的实例化不是由Spring控制的,因此不能直接在类的字段上使用@Autowired进行自动注入。
public void setUserMapper(UserMapper userMapper) { ... }
:这个方法是一个通过@Autowired
注解的setter方法。Spring会自动调用这个方法并传入一个UserMapper
的实例,这样即使在非标准的Spring组件中也能实现依赖注入。这里通过传递的userMapper
参数来设置静态字段userMapper
的值。
解决方案
为了在WebSocketServer
这样的类中注入Spring管理的bean,解决方案是创建一个非静态的setter方法
,并在这个方法上使用@Autowired
注解。Spring在启动时会自动调用这个方法,并注入所需的依赖。然后,这个方法内部再将注入的依赖赋值给静态变量,这样即便是WebSocket的生命周期管理不由Spring控制,我们也能在类中使用由Spring管理的依赖。
注意事项
使用静态字段持有Spring管理的bean是一种特殊情况下的解决方案,通常不推荐这样做,因为它违背了Spring的依赖注入原则,可能会导致代码难以测试和维护。不过,在某些特殊场景(如此处的WebSocket服务端实现)下,这种方式可以作为一种权宜之计。