问题由来?
这几天自己想捣鼓一个im项目,springboot集成Netty来做服务端处理和转发消息,结果发现handler中使用@Autowired注入的bean全部为null,试图找出原因。
为什么会出现注入bean全部为null?
可能我们潜意识的认为,我们使用@Autowired注入的bean应该会有对应的实例化对象,因为全部是通过spring进行bean的创建管理和注入的。那是因为我们使用的spring的注解,但是Netty的handler是我们通过new 出来的对象,spring是管不到的,即无法注入bean;例外还有一点不同的是,spring默认创建的对像都是单例的,这种可能也不太适合netty。
解决方式
网上的几种方式(无论是实现ApplicationContextAware类通过获取bean还是将要注入的 service 改成 static,再通过set方法,或者是通过@PostConstruct注解init()初始化)获取的对像仍然全部为null,可能我的姿势不大对~~
下面说说我的代码是怎么样的(要不然怎么会知道为什么我的姿势不对呢?☹️)
注入bean为null时的代码
springboot的启动类
@SpringBootApplication
public class ImSeverApplication {
@Autowired
private NettyBootstrap nettyBootstrap;
public static void main(String[] args) {
SpringApplication.run(ImSeverApplication.class, args);
}
@PostConstruct
public void startNetty() {
nettyBootstrap.setPort(8888).start();
}
}
netty 的启动引导类
@Slf4j
@Component
public class NettyBootstrap {
private int port;
public NettyBootstrap() {
}
public NettyBootstrap setPort(int port) {
this.port = port;
return this;
}
public void start() {
NioEventLoopGroup boss = new NioEventLoopGroup();
NioEventLoopGroup worker = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(boss, worker)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitiallizer())
.option(ChannelOption.SO_BACKLOG, 1024)
.childOption(ChannelOption.SO_KEEPALIVE, true);
try {
ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
log.info("Netty Server Start Success");
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
}
ChannelInitiallizer 类
public class ChannelInitiallizer extends ChannelInitializer {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline()
.addLast("codec", new HttpServerCodec())
.addLast("chunked", new ChunkedWriteHandler())
.addLast("aggreator", new HttpObjectAggregator(65536))
.addLast(new WebSocketServerProtocolHandler("/ws/chat"))
.addLast(new BinaryWebSocketFrameHandler());
}
}
BinaryWebSocketFrameHandler 类
public class BinaryWebSocketFrameHandler extends SimpleChannelInboundHandler {
@Autowired
private RedisUtil redisUtil ;
@Autowired
private UserGroupService userGroupService ;
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, BinaryWebSocketFrame binaryWebSocketFrame){
}
}
自己的解决方式(构造方式注入对象,红框内即为变动后的代码)
可能方法还是不那么尽人意,但还是解决了我的问题,希望能帮到~