【前言】
在没用SpringBoot加载Netty的时候,我觉得单独靠Thread启动一个Netty也挺好。后来因为工作习惯的改变,越来越多的依赖AOP、SOA,觉得SpringBoot管理起Netty后,其实也还好,因为很少在Netty上操作ORM,唯一有点喜欢的就是基于AOP的Log。
【入口】
之前我写好一个Netty Server后,会让他implements Runnable/Callable,然后写到Thread里面start一下。现在看一下springboot怎么装载Netty。
先给写好的Netty Server加上注解,定义成Service
@Service
public class WebSocketServer {
@PostConstruct
public void init() {
// 服务初始化代码放这里
}
@PreDestroy
public void destroy() {
...
}
}
这是典型的Bean定义格式。如果想指定参数,如监听端口,在init()方法用spring模板从资源文件中加载就好了,这里不细说。@PreDestroy部分写上销毁代码,比如连接池销毁,监听的RunLoop销毁
public void destroy() {
if (bossLoop !=null) {
bossLoop.shutdownGracefully();
}
if (workerLoop !=null) {
workerLoop.shutdownGracefully();
}
}
外部SpringBoot
@SpringBootApplication
public class App implements CommandLineRunner, ApplicationContextAware {
@Resource
private WebSocketServer wsServer; // 注入NettyServer
public staticvoid main(String[] args) {
SpringApplication.run(App.class,args); // 启动SpringBoot,运行这行代码后才开始Bean注入
}
}【非Bean启动的服务】
在SpringBoot中我们的App类还可以专门为服务指定入口,用覆盖的run方法
@Override
public void run(String...args) throws Exception {
etcdUtil.regist();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
etcdUtil.destroy();
}
});
}
【普通Java的Class实例获取Bean】
我推荐实现ApplicationContextAware接口,因为在Netty中,很多实例是不太方便作为Component的,比如Handler。所以在这些Handler里面想加载Bean,需要用到ApplicationContext的getBean能力。因此在入口类App中,推荐实现上下文的加载。
private static ApplicationContext applicationContext;
@SuppressWarnings("static-access")
@Override
public void setApplicationContext(ApplicationContextapplicationContext) throws BeansException {
this.applicationContext =applicationContext;
}
public static
return applicationContext.getBean(clazz);
}
这样就可以通过getBean方法获取Bean【销毁】
按上面的操作一遍没啥问题,只不过有时候除了Netty还有可能会连接其他的东西,比如之前连过etcd,jedis。所以需要一个销毁资源的入口。依然在App类里面